Quickstart
Verify the key, resolve a record, and write your first approved note back to ShelfCycle.
This guide assumes you have a ShelfCycle API key. The key is scoped to one tenant and issued to one acting user. Store it locally and read it from the environment at runtime.
Never paste the key into a prompt, chat message, log line, or source control. Give local tooling the environment variable name, not the secret value.
1. Configure the environment
Set the key and base URL in a local .env file.
SHELFCYCLE_API_KEY=sk_...
SHELFCYCLE_API_BASE_URL=https://app.shelfcycle.com/api/v1
For local ShelfCycle development, use:
http://localhost:3000/api/v1
2. Verify the key
Call GET /me before any workflow step. It returns the org, key preview, scopes, and acting user without revealing the secret.
curl "$SHELFCYCLE_API_BASE_URL/me" \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "X-ShelfCycle-Client: Email notes automation"
The response should include the expected tenant and the scopes your workflow needs.
{
"data": {
"apiVersion": "v1",
"org": { "id": "org-id", "name": "Northstar Chemical" },
"key": {
"id": "api-key-id",
"name": "Email notes automation",
"preview": "sk_...abcd",
"scopes": ["search:read", "notes:write"],
"expiresAt": null
},
"actor": { "type": "user", "id": "user-id", "displayName": "Jordan Buyer" }
}
}
Use the key preview and org name as the wiring check. Never print the full key.
3. Resolve the target record
Before any write, search for the exact record to attach context to. GET /search takes a required q, an optional comma-separated types list, and an optional limit from 1 to 20.
curl "$SHELFCYCLE_API_BASE_URL/search?q=Northstar&types=customer,contact&limit=10" \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "X-ShelfCycle-Client: Email notes automation"
{
"data": [
{
"type": "contact",
"id": "contact-id",
"displayName": "Jordan Buyer",
"subtitle": "Northstar Chemical | jordan@example.com | President",
"url": "https://app.shelfcycle.com/org-northstar/customers/customer-id/contacts",
"archived": false,
"matchedFields": [
{ "field": "email", "label": "Email", "value": "jordan@example.com" },
{ "field": "parent.name", "label": "Customer", "value": "Northstar Chemical" }
],
"parent": { "type": "customer", "id": "customer-id", "displayName": "Northstar Chemical" }
}
],
"meta": {
"requestId": "request-id",
"limit": 10,
"types": ["customer", "contact"],
"rankingIsContractual": false,
"truncated": false,
"durationMs": 24
}
}
Show the candidate to a person and ask them to confirm the exact {type,id} before writing. If meta.truncated is true, narrow the query first.
4. Write the approved note
Use POST /notes after the target has been confirmed. Send a stable Idempotency-Key built from source facts, not a random value.
curl "$SHELFCYCLE_API_BASE_URL/notes" \
-X POST \
-H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: gmail-thread-123:customer-id:create-note" \
-d '{
"primarySubject": { "type": "customer", "id": "customer-id" },
"linkedRecords": [
{ "type": "contact", "id": "contact-id" },
{ "type": "product", "id": "product-id" }
],
"noteType": "EMAIL",
"title": "Inbound product approval thread",
"body": "Jordan approved adding the new contact and asked for follow-up on acetone availability.",
"happenedAt": "2026-05-28T16:00:00.000Z"
}'
{
"data": {
"id": "note-id",
"type": "note",
"url": "https://app.shelfcycle.com/org-northstar/notes/note-id",
"createdAt": "2026-05-29T14:35:00.000Z",
"updatedAt": "2026-05-29T14:35:00.000Z",
"createdBy": { "type": "user", "id": "user-id", "displayName": "Jordan Buyer" },
"idempotencyStatus": "created"
}
}
Hand the returned url to the person who approved the write so they can verify the note in ShelfCycle.
Do not generate a random idempotency key for each retry. The same source event must reuse the same key. The same key with a different body returns 409 idempotency_key_reused.
5. Stay inside v1 boundaries
v1 supports search, safe detail reads, approved contact creates and updates, and approved note creates and updates.
It does not create or update customers, suppliers, products, orders, inventory, pricing, costs, or accounting records. Order cards are read-only context. Do not send an order as a note subject or linked record.
