Notes

List, read, create, and update notes on confirmed customers, suppliers, and products.

Use this guide after selecting one customer, supplier, or product. For complete counts, rankings, and recent excerpts across notes, use the Note activity guide.

List subject notes

GET /notes

Required scope:

notes:read

GET /notes requires a visible subject and returns metadata only. It is not a global note search.

curl "$SHELFCYCLE_API_BASE_URL/notes?primarySubjectType=customer&primarySubjectId=customer-id&limit=10" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY"

Add happenedAtFrom and happenedAtTo to narrow the selected subject's notes by organization-calendar day. Add noteType to narrow the list to one supported type.

curl "$SHELFCYCLE_API_BASE_URL/notes?primarySubjectType=customer&primarySubjectId=customer-id&happenedAtFrom=2026-07-13&happenedAtTo=2026-07-19&noteType=EMAIL&limit=10" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY"

Fetch the body only after selecting one visible note with GET /notes/{id}.

Create a note

POST /notes

Required scope:

notes:write

Required header:

Idempotency-Key: <stable-key>

Add dryRun=true to check the exact intended note write without mutating records.

primarySubject can be customer, supplier, or product.

linkedRecords can be customer, supplier, product, contact, or location. ShelfCycle renders those records as mention and backlink rows and dedupes them with the primary subject.

Supported noteType values:

NOTE, EMAIL, PHONE_MEETING, VIRTUAL_MEETING, PHYSICAL_MEETING, SAMPLE_REQUEST, OPPORTUNITY, QUOTE

Request

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" },
      { "type": "supplier", "id": "supplier-id" }
    ],
    "noteType": "EMAIL",
    "title": "Inbound product thread",
    "body": "Jordan asked for follow-up on acetone availability.",
    "happenedAt": "2026-05-28T16:00:00.000Z"
  }'

Response

{
  "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" },
    "createdVia": { "type": "public_api", "actorUserId": "user-id" },
    "requestedVia": { "type": "api_key", "id": "api-key-id", "purpose": "Workflow for creating notes from source emails" },
    "idempotencyStatus": "created"
  }
}

Repeating the same route plus Idempotency-Key with the same request body in the same org returns the existing note with idempotencyStatus: "replayed" and does not mutate the existing note.

Read a note

GET /notes/{id}

Required scope:

notes:read

For v1 compatibility, notes:write can read API-created notes. The response includes the latest updatedAt value to use as If-Match for updates.

Update a note

PATCH /notes/{id}

Required scope:

notes:write

Required header:

If-Match: <updatedAt from latest GET /notes/{id}>

Sparse patch fields:

{
  "title": "Updated title",
  "body": "Updated note body.",
  "happenedAt": "2026-05-28T18:00:00.000Z",
  "noteType": "PHONE_MEETING",
  "linkedRecords": [
    { "type": "customer", "id": "customer-id" },
    { "type": "contact", "id": "contact-id" }
  ]
}

PATCH only updates notes created through the public API for the same org. It cannot change the primary subject, creator, org, idempotency identity, archive state, or deletion state.

Warning

Use customer, supplier, or product records as note subjects and links. Order context can be included in the note body.