curl --request POST \
--url https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"last_name": "Obi-Nwosu",
"phone": null,
"relationship": {
"director": true
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({last_name: 'Obi-Nwosu', phone: null, relationship: {director: true}})
};
fetch('https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id}"
payload = {
"last_name": "Obi-Nwosu",
"phone": None,
"relationship": { "director": True }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id}"
payload := strings.NewReader("{\n \"last_name\": \"Obi-Nwosu\",\n \"phone\": null,\n \"relationship\": {\n \"director\": true\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))
}{
"id": "per_3a91c0d7",
"first_name": "Ada",
"last_name": "Obi-Nwosu",
"dob": "1990-04-12",
"address": {
"line1": "14 Balogun Street",
"city": "Lagos",
"state": "Lagos",
"postal_code": "101241",
"country": "NG"
},
"phone": null,
"email": "ada@example.com",
"id_number_provided": true,
"relationship": {
"representative": true,
"owner": true,
"director": true,
"executive": false,
"percent_ownership": 60,
"title": "Founder"
},
"verification": {
"status": "verified",
"document_provided": true,
"failure_reason": null
},
"created_at": "2026-08-10T09:31:12.000Z",
"updated_at": "2026-08-11T16:22:03.884Z"
}{
"detail": "Invalid request parameters",
"error_code": "VALIDATION_ERROR",
"errors": [
{
"field": "amount",
"message": "Amount must be a positive decimal string",
"type": "value_error"
}
]
}{
"detail": "Invalid API key",
"error_code": "UNAUTHORIZED"
}{
"detail": "API key does not have permission for this operation",
"error_code": "FORBIDDEN"
}{
"detail": "Resource not found",
"error_code": "NOT_FOUND"
}{
"detail": "Validation failed for one or more fields",
"error_code": "VALIDATION_ERROR",
"doc_url": "https://docs.bachs.io/api-reference/error-reference#general",
"errors": [
{
"field": "name",
"message": "This field is required",
"type": "missing"
}
]
}{
"detail": "Rate limit exceeded. Please retry after a few seconds.",
"error_code": "TOO_MANY_REQUESTS"
}Update a person
Edit one person in place. Keys you omit are left alone; sending a key as null clears it.
curl --request POST \
--url https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"last_name": "Obi-Nwosu",
"phone": null,
"relationship": {
"director": true
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({last_name: 'Obi-Nwosu', phone: null, relationship: {director: true}})
};
fetch('https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id}"
payload = {
"last_name": "Obi-Nwosu",
"phone": None,
"relationship": { "director": True }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.bachs.io/v1/accounts/{account_id}/persons/{person_id}"
payload := strings.NewReader("{\n \"last_name\": \"Obi-Nwosu\",\n \"phone\": null,\n \"relationship\": {\n \"director\": true\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))
}{
"id": "per_3a91c0d7",
"first_name": "Ada",
"last_name": "Obi-Nwosu",
"dob": "1990-04-12",
"address": {
"line1": "14 Balogun Street",
"city": "Lagos",
"state": "Lagos",
"postal_code": "101241",
"country": "NG"
},
"phone": null,
"email": "ada@example.com",
"id_number_provided": true,
"relationship": {
"representative": true,
"owner": true,
"director": true,
"executive": false,
"percent_ownership": 60,
"title": "Founder"
},
"verification": {
"status": "verified",
"document_provided": true,
"failure_reason": null
},
"created_at": "2026-08-10T09:31:12.000Z",
"updated_at": "2026-08-11T16:22:03.884Z"
}{
"detail": "Invalid request parameters",
"error_code": "VALIDATION_ERROR",
"errors": [
{
"field": "amount",
"message": "Amount must be a positive decimal string",
"type": "value_error"
}
]
}{
"detail": "Invalid API key",
"error_code": "UNAUTHORIZED"
}{
"detail": "API key does not have permission for this operation",
"error_code": "FORBIDDEN"
}{
"detail": "Resource not found",
"error_code": "NOT_FOUND"
}{
"detail": "Validation failed for one or more fields",
"error_code": "VALIDATION_ERROR",
"doc_url": "https://docs.bachs.io/api-reference/error-reference#general",
"errors": [
{
"field": "name",
"message": "This field is required",
"type": "missing"
}
]
}{
"detail": "Rate limit exceeded. Please retry after a few seconds.",
"error_code": "TOO_MANY_REQUESTS"
}Authorizations
Bearer token authentication. Pass your API key as Authorization: Bearer sk_.... See Authentication for keys, scopes, and sandbox vs production.
Path Parameters
The account to act on. It must be one of your own accounts; any other ID returns 404.
The person on that account.
Body
On edit, omitted keys are left alone and an explicit null clears the field. Naming one relationship flag leaves the others as they were.
The person's given name as it appears on their government ID, since a mismatch against the document is the most common reason identity verification is rejected. On an update, omitting this key leaves the stored value alone and sending it as null clears it.
"Ada"
The person's family name as it appears on their government ID, checked against the document alongside first_name. On an update, omitting this key leaves the stored value alone and sending it as null clears it.
"Obi"
ISO-8601 date, YYYY-MM-DD.
The person's residential address, as an object with line1, city, state and country (two-letter ISO 3166-1), plus an optional postal_code. It is written whole rather than merged, so send every key you want kept; on an update, omitting this key leaves the stored address alone and sending it as null clears it.
A contact number for this person, kept with their identity record and passed on when their identity is checked, 32 characters or fewer. On an update, omitting this key leaves the stored value alone and sending it as null clears it.
"+2348012345678"
This person's own email address, separate from the account's contact_email, and used for correspondence about their verification rather than the account's. It must be a valid address or the request fails with 422; on an update, omitting this key leaves the stored value alone and sending it as null clears it.
"ada@example.com"
The person's government ID number. It is write-only: it is never echoed back, and the response reports id_number_provided instead. On an update, omitting this key leaves the stored number alone and sending it as null clears it.
"22345678901"
Role flags. One person is commonly several of these at once, which is why they are flags on one person rather than separate collections.
Show child attributes
Show child attributes
Response
The updated person.
The person's identifier, prefixed per_. Requirement keys are anchored to it, so persons.per_3a91c0d7.id_document names exactly who owes a document.
"per_3a91c0d7"
The person's given name as recorded, or null when it has not been supplied yet. It is the name their identity document is checked against.
"Ada"
The person's family name as recorded, or null when it has not been supplied yet. It is checked against the identity document alongside first_name.
"Obi"
ISO-8601 date, YYYY-MM-DD.
"1990-04-12"
The person's residential address, carrying the line1, city, state, postal_code and country keys that were written, or null when no address has been supplied. It is stored whole, so a later write replaces it rather than merging into it.
The contact number recorded for this person, returned exactly as it was sent, or null when none has been supplied.
"+2348012345678"
The email address recorded for this person, or null when none has been supplied. It belongs to the person, not to the account, so it differs from the account's contact_email.
"ada@example.com"
true when a government ID number is held for this person, false when none has been supplied. The number itself is write-only and never returned, so this flag is how you tell whether you still need to collect one.
true
Role flags. One person is commonly several of these at once, which is why they are flags on one person rather than separate collections.
Show child attributes
Show child attributes
What has been established about this person. How it was established is not reported.
Show child attributes
Show child attributes
When the person was added to the account, ISO 8601 in UTC.
"2026-08-10T09:31:12.000Z"
When the person record last changed, ISO 8601 in UTC. A verification outcome we record moves it as well as your own writes, so do not read it as the time of your last edit.
"2026-08-11T14:05:40.219Z"

