11. Create a sandbox key
In Bodo: Settings › Interfaces › API keys › “Create key”.
| Step in the wizard | Value for the quickstart |
|---|---|
| Environment | test, binds to “Musterfirma GmbH (Sandbox)” |
| Scope | Contacts: read & write · Companies: read · Rest: no access |
| IP binding | your current IP, e.g. 198.51.100.7/32 (required for writes) |
| Expiry | 30 days (default) |
The API is already on in the sandboxYour organization’s sandbox already has
apiAccess switched on, with test data only. So the quickstart needs no approval from an admin. The one precondition: your organization has declared in Bodo whether professional secrecy applies to it; without that declaration the API stays off in the sandbox as well. For a live key (live) an org admin first has to enable the API of your organization under Settings › Interfaces › API; until then the button is missing there.The secret is shown only once. Keep it in an environment variable:
export BODO_API_KEY="bodo_uk_test_…"22. Who am I?
GET /v1/me names the principal, the organization and your own key with expiry, pin and effective scopes.curl https://api.bodo-app.com/v1/me \
-H "Authorization: Bearer $BODO_API_KEY"HTTP/1.1 200 OK
Bodo-Version: 2026-11-01
Request-Id: req_01JB6…
{
"authMethod": "apiKey",
"principalType": "user",
"principalId": "usr_…",
"principalName": "Max Mustermann",
"organization": {
"id": "org_…",
"name": "Musterfirma GmbH (Sandbox)"
},
"key": {
"kidShort": "…Kx9a",
"environment": "test",
"versionPin": "2026-11-01",
"expiresAt": "2026-12-03T09:00:00Z"
},
"grant": null,
"scopes": [
"contacts:read",
"contacts:write",
"companies:read"
],
"openFamilies": [],
"apiVersion": "2026-11-01"
}33. Create a contactPreview
Writes start in the preview channel and therefore need
Bodo-Preview: true. With the first follow-up version, writes for contacts, companies and tasks move to stable and the header is no longer needed. Idempotency-Key is required for POST; with the same key a retry is safe.curl -X POST https://api.bodo-app.com/v1/contacts \
-H "Authorization: Bearer $BODO_API_KEY" \
-H "Bodo-Preview: true" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"firstName":"Erika","lastName":"Mustermann","email":"erika@musterfirma.de"}'Or with the SDK, which sets the preview header and the idempotency key itself:
// Portal D2 · Quickstart — steps 2 and 3 with the SDK: who am I, then one contact.
// Run: BODO_API_KEY=bodo_uk_test_… bun examples/quickstart.ts
import { Bodo, BodoApiError } from "@bodo/api";
const bodo = new Bodo({
apiKey: process.env.BODO_API_KEY,
preview: true, // writes are in the preview channel: sends Bodo-Preview: true
});
// Step 2 · Who am I?
const me = await bodo.me();
console.log(me.principalType, me.authMethod);
// Step 3 · Create a contact. The SDK sets the Idempotency-Key itself, retries included.
try {
const contact = await bodo.contacts.create({
firstName: "Erika",
lastName: "Mustermann",
email: "erika@musterfirma.de",
});
console.log(contact.id, contact.displayName);
} catch (err) {
if (err instanceof BodoApiError) {
console.error(err.code, err.requestId); // the stable code, never the text
}
throw err;
}- 201 Created
- Location: /v1/contacts/con_…
- ETag
44. Look it up in Bodo
The contact is in the sandbox. Its timeline shows the plug mark, so the origin is visible.
MMMax Mustermann created the contact Erika Mustermann, via the API.Done through the APISandboxjust now