{
  "schema": "aaes/capability-pack/1",
  "provider": "salesloft",
  "version": "1.0.0",
  "description": "Salesloft: read people, accounts, outreach sequences and activity history, and enroll a person in a sequence that can automatically send email.",
  "notes": "The endpoint host api.salesloft.com is Salesloft's real shared API host and stays real; the pack pins the v2 base path and there is no per-customer host to substitute. Reads are registered against the collection endpoints only: single-record reads (GET /v2/people/{id}, GET /v2/cadences/{id}, GET /v2/cadence_memberships/{id} and the other by-id paths) are not registered by this pack. The activities read is the activity-history collection (GET /v2/activity_histories), which Salesloft documents as returning the customer's past activities as found on the Salesloft Activity Feed.\n\nDocumented exclusions — this pack does not register: person create, update or delete; account create or update; cadence creation, step management, import or deletion; cadence-membership reads (GET /v2/cadence_memberships), updates and deletion, and bulk cadence-membership creation; one-off email sends and call logging under /v2/activities; tasks, notes, meetings, conversations and transcriptions; crm_activities; people data redaction and the other privileged-scope operations; and webhooks.\n\nApproval classification: sales engagement is send-first. Creating a cadence membership adds a named person to a cadence, and a Salesloft cadence is a multi-step outreach sequence — its automated email steps are sent by the platform without further human action, while call, task and other manual steps are only queued for a user to execute — the unrestricted automated-send effect is what governs the tier: a delivered email cannot be recalled, so the capability declares create and send, and send keeps the tier at the minimum R3 tier; send is one of the designated actions requiring human approval.\n\nDocumentation review is complete. Bind the owner placeholders and obtain deployment-specific approval before enabling; live tenant testing remains outstanding. Credential custody was reviewed on 2026-09-21 against this pack's custody model — a scoped customer API key (or, where the deployment runs the OAuth flow, a short-lived access token) held in the customer's vault — with the following findings (the full credential contract is in the credential note).\n\nIssuance authority and delegation: the customer provisions API keys in Salesloft Account > Your Applications > API Keys and OAuth apps under Your Applications > OAuth Applications, and both act on behalf of the issuing or authorizing user, so issuance authority sits with the customer's own admin; OAuth is the only method Salesloft approves for partner applications. Scope: both modes are scoped at creation — at least one scope is required before a key can be saved, and a key's scopes can be narrowed later by editing it; the retrieved pages show the <resource>:<action> scope naming but do not enumerate the full catalog, so exact scope names are confirmed in the UI at creation.\n\nAudience: no audience mechanism is documented — the bearer value authorizes against api.salesloft.com, and audience binding beyond that is not established. TTL: API keys have no documented expiry and remain valid until deleted; OAuth access tokens expire after 7,200 seconds.\n\nRefresh ownership: in OAuth mode every refresh revokes all older refresh tokens, so an external process must always store the newest refresh token, and in API-key mode there is no refresh at all; in both modes the executor injects the stored value verbatim and performs no token lifecycle itself.\n\nRevocation: API keys are revoked by deleting them in the account UI; for OAuth the reviewed documentation establishes grant invalidation only through the invalid_grant error and documents no token-revocation endpoint, so an OAuth revocation endpoint is not established. Executor access and replay/exposure: the executor reads only the vault reference and injects the complete Authorization header value; Salesloft warns that API keys function like logins, so the vault reference is the only place the value may live; both modes are bearer credentials replayable while valid, and OAuth's 7,200-second TTL and forced refresh rotation bound a stolen token's window while an API key has no such bound until deleted.\n\nAlternate access paths: the Salesloft web UI and any other integrations retain access outside this pack, and deleting the key or revoking the grant closes only this path.",
  "credential": {
    "secret_ref_id": "secret-ref-salesloft-api-key",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "A Salesloft customer API key, held in the client's own secret manager. Salesloft provisions API keys in Salesloft Account > Your Applications > API Keys; a key takes the form 'ak' followed by a 64-character hexadecimal string, acts on behalf of the issuing user, and is scoped at creation. The stored material must be the complete Authorization header value: the scheme 'Bearer', one separating space, then the key.\n\nIssue the key from a dedicated least-privilege integration user with only the scopes the enabled capabilities need — read scopes for people, accounts, cadences and activity_histories for the registered reads, and the cadence-membership write scope only if the create capability is enabled (Salesloft's documentation shows the <resource>:<action> scope naming, for example 'accounts:write calls:read', but the retrieved pages did not enumerate the full scope catalog, so confirm the exact scope names in the Salesloft API-key UI at creation — at least one scope must be selected before a key can be saved); keys function like logins, so the vault reference is the only place the value may live.\n\nExpiry and revocation: Salesloft's API-key documentation documents no expiry for API keys — a key remains valid until it is deleted in Salesloft Account > Your Applications > API Keys, and its scopes can also be narrowed later by editing the key. Where the deployment instead runs the OAuth 2.0 authorization-code flow (the only method Salesloft approves for partner applications): access tokens expire after 7,200 seconds, and on every refresh all older refresh tokens are revoked, so the newest refresh token must always be stored — refresh ownership sits with an external process, and the executor injects the stored value verbatim and performs no token lifecycle itself in either mode. OAuth revocation: the retrieved OAuth documentation documents grant invalidation through its invalid_grant error (an authorization grant that is 'invalid, expired, revoked' can no longer mint tokens) but no explicit access-token revocation endpoint, so revoke the user's authorization grant to block further issuance and refresh, and treat an already-issued access token as valid for at most the remainder of its 7,200-second lifespan.\n\nExecutor hygiene: the value must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "salesloft.people.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.salesloft.com"
      ],
      "endpoint": "https://api.salesloft.com/v2/people",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-salesloft-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "salesloft-people",
      "description": "List person records: names, email addresses, phone numbers and titles, which identify named people, so the read is classified as pii (personal data). The registered path covers the collection read only — single-person reads (GET /v2/people/{id}) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "salesloft.accounts.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.salesloft.com"
      ],
      "endpoint": "https://api.salesloft.com/v2/accounts",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-salesloft-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "salesloft-accounts",
      "description": "List account records: company names, domains and firmographic fields — customer data, classified as internal data. The registered path covers the collection read only — single-account reads (GET /v2/accounts/{id}) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "salesloft.cadences.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.salesloft.com"
      ],
      "endpoint": "https://api.salesloft.com/v2/cadences",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-salesloft-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "salesloft-cadences",
      "description": "List cadence records: names, team-cadence flags and cadence structure — engagement-playbook metadata revealing sales operations, classified as internal data. The registered path covers the collection read only — single-cadence reads (GET /v2/cadences/{id}) and cadence-membership queries are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "salesloft.activities.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.salesloft.com"
      ],
      "endpoint": "https://api.salesloft.com/v2/activity_histories",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-salesloft-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "salesloft-activities",
      "description": "Read the activity-history collection: the customer's past activities as shown on the Salesloft Activity Feed — sends, replies, calls and step executions tied to named users and people, which is behavioural personal data, so the read is classified as pii (personal data).",
      "requires_review": true
    },
    {
      "capability_id": "salesloft.cadence-memberships.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "api.salesloft.com"
      ],
      "endpoint": "https://api.salesloft.com/v2/cadence_memberships",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-salesloft-api-key",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "create",
        "send"
      ],
      "resource_id": "salesloft-people",
      "description": "Add one person to a cadence (a sequence of outreach steps). The body requires person_id and cadence_id, both visible to the authenticated user.\n\nSalesloft sends automated email steps without another human action. It queues call, task, and other manual steps for a user to perform. Because enrollment can send email that cannot be recalled, this capability declares create and send at R3.\n\nOn supported AAES-mediated execution paths, the send action requires approval by an authorized person; this does not prevent calls through bypass or observation-only paths.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "salesloft-people",
      "kind": "api",
      "locator": "https://api.salesloft.com/v2/people",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "salesloft-accounts",
      "kind": "api",
      "locator": "https://api.salesloft.com/v2/accounts",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "salesloft-cadences",
      "kind": "api",
      "locator": "https://api.salesloft.com/v2/cadences",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "salesloft-activities",
      "kind": "api",
      "locator": "https://api.salesloft.com/v2/activity_histories",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://developers.salesloft.com/docs/api/people-index/ (retrieved 2026-09-21)",
      "https://developers.salesloft.com/docs/api/accounts-index/ (retrieved 2026-09-21)",
      "https://developers.salesloft.com/docs/api/cadences-index/ (retrieved 2026-09-21)",
      "https://developers.salesloft.com/docs/api/activity-histories-index/ (retrieved 2026-09-21)",
      "https://developers.salesloft.com/docs/api/cadence-memberships-create/ (retrieved 2026-09-21)",
      "https://developers.salesloft.com/docs/platform/api-basics/api-key-authentication/ (retrieved 2026-09-21)",
      "https://developers.salesloft.com/docs/platform/api-basics/oauth-authentication/ (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
