> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ancha.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These docs describe the Ancha CLI, npm package @ancha-labs/cli version 0.1.4, and the hosted workspace at app.ancha.io. Coding agents should start at https://docs.ancha.io/coding-agents. Run the CLI as `ancha` after `npm install -g @ancha-labs/cli`, or as `npx -y @ancha-labs/cli@0.1.4` without installing. Pass --json for machine-readable output, or set ANCHA_JSON=1. Every command ends with a `next:` line naming the next command. Exit codes: 0 pass, 1 a check failed or a comparison regressed, 2 usage, config or authentication error, 3 infrastructure error, 4 unimplemented endpoint with --strict.

# Salesforce

> A stateful replica of Salesforce's REST API v67.0: accounts, contacts, leads, opportunities, campaigns and campaign members, with SOQL queries and composite requests.

The Salesforce replica implements REST API v67.0 for six standard objects, a subset of SOQL and composite requests. Its key is `salesforce`.

## Connect

| Variable | Value |
| - | - |
| `SALESFORCE_INSTANCE_URL` | The instance URL. Append `/services/data/v67.0/...`. |
| `SALESFORCE_ACCESS_TOKEN` | Fake session token. Send `Authorization: Bearer <token>`. |

```js Node theme={null}
const response = await fetch(process.env.SALESFORCE_INSTANCE_URL + '/services/data/v67.0/query?q=' + encodeURIComponent('SELECT Id, Name FROM Account'), { headers: { Authorization: 'Bearer ' + process.env.SALESFORCE_ACCESS_TOKEN } });
const accounts = await response.json();
```

This is what `ancha connect salesforce --lang ts` prints. There is no OAuth or SOAP login: use the token as given.

## Endpoints

| Method | Path |
| - | - |
| `GET` | `/services/data/` |
| `GET` | `/services/data/v67.0` |
| `GET` | `/services/data/v67.0/sobjects` |
| `GET` | `/services/data/v67.0/sobjects/:type` |
| `GET` | `/services/data/v67.0/sobjects/:type/describe` |
| `GET` | `/services/data/v67.0/sobjects/:type/:id` |
| `POST` | `/services/data/v67.0/sobjects/:type` |
| `PATCH` | `/services/data/v67.0/sobjects/:type/:id` |
| `DELETE` | `/services/data/v67.0/sobjects/:type/:id` |
| `GET` | `/services/data/v67.0/sobjects/:type/:field/:value` |
| `PATCH` | `/services/data/v67.0/sobjects/:type/:field/:value` |
| `GET` | `/services/data/v67.0/query` |
| `GET` | `/services/data/v67.0/query/:locator` |
| `POST` | `/services/data/v67.0/composite` |

All endpoints are partial. `GET /services/data/` needs no token and reports version 67.0. Unsupported objects, fields and syntax return Salesforce's error shape with an `ancha: not implemented:` message and `x-ancha-gap: 1`.

## Objects

| Object | Fields besides `Id`, `CreatedDate`, `LastModifiedDate` and `External_Id__c` |
| - | - |
| Account | `Name`, `Industry`, `Type`, `Website`, `Description`, `BillingCountry`, `NumberOfEmployees`, `AnnualRevenue` |
| Contact | `FirstName`, `LastName`, `AccountId`, `Email`, `Title`, `Phone` |
| Lead | `FirstName`, `LastName`, `Company`, `Email`, `Title`, `Status`, `LeadSource`, `Industry` |
| Opportunity | `Name`, `AccountId`, `StageName`, `CloseDate`, `Amount`, `Probability`, `LeadSource`, `Description`, `CampaignId`, and read-only `IsClosed` and `IsWon` |
| Campaign | `Name`, `Type`, `Status`, `IsActive`, `StartDate`, `EndDate`, `BudgetedCost`, `ActualCost`, `Description`, `ClientAccount__c` |
| CampaignMember | `CampaignId`, `ContactId` or `LeadId`, `Status` |

`External_Id__c` is a unique external ID on every object, usable in `/sobjects/:type/External_Id__c/:value`. Unknown fields are rejected. Relationships must point at existing records of the right object.

## SOQL

```sql theme={null}
SELECT Id, Name, Amount FROM Opportunity
WHERE Amount >= 50000 AND StageName IN ('Qualification', 'Proposal/Price Quote')
ORDER BY Amount DESC LIMIT 20 OFFSET 0
```

* One object, explicit fields, predicates joined with AND, one `ORDER BY` field, `LIMIT` and `OFFSET`.
* Operators `=`, `!=`, `<`, `<=`, `>`, `>=`, `IN`, `LIKE`. String comparisons ignore case.
* Pages hold 2,000 records by default; `nextRecordsUrl` reads the next page from a snapshot taken when the query ran.
* Relationship queries, subqueries, aggregates, `COUNT`, `GROUP BY`, `OR`, `NOT`, date functions and `FIELDS()` are coverage gaps.

`POST /composite` runs 1 to 25 subrequests in order, with references such as `@{created.id}` and optional `allOrNone` rollback.

## Starter data

The `salesforce-starter` dataset is the org **Acme** (`00D000000000001AAA`).

| Object | ID | Record |
| - | - | - |
| Account | `001000000000001AAA` | Ridgeway Robotics, manufacturing, prospect, 850 employees |
| Account | `001000000000002AAA` | Helix Manufacturing, a customer. Not accessible to the token. |
| Account | `001000000000003AAA` | Pinecrest Health, healthcare, customer, 1,900 employees |
| Account | `001000000000004AAA` | Bluefield Logistics, transportation, prospect, 620 employees |
| Account | `001000000000005AAA` | Kestrel Credit Union, banking, customer, 410 employees |
| Account | `001000000000006AAA` | Summit Freight, transportation, customer, 350 employees |
| Account | `001000000000007AAA` | Lakeview Retail, retail, prospect, 1,200 employees |
| Contact | `003000000000001AAA` to `003000000000006AAA` | Erin Walsh (Ridgeway Robotics), Nora Bell (Pinecrest Health), Owen Hart (Bluefield Logistics), Carla Diaz (Kestrel Credit Union), Daniel Reyes (Summit Freight) and Rob Fisher (Lakeview Retail) |
| Lead | `00Q000000000001AAA` | Theo Reed, Beacon Logistics, "Working - Contacted", from LinkedIn |
| Lead | `00Q000000000002AAA` to `00Q000000000004AAA` | Lucy Grant (Harbor Foods, "Open - Not Contacted"), Hannah Cole (Redwood Labs, "Working - Contacted") and Sean Walker (Copperline Energy, "Closed - Not Converted") |
| Opportunity | `006000000000001AAA` | "Ridgeway Robotics — Analytics rollout", Proposal/Price Quote, 96000, closes 2026-11-30, in the Q4 pilot campaign |
| Opportunity | `006000000000002AAA` to `006000000000006AAA` | "Pinecrest Health — Enterprise plan" (Closed Won, 144000), "Bluefield Logistics — Pilot" (Proposal/Price Quote, 36000), "Kestrel Credit Union — Renewal" (Negotiation/Review, 48000), "Summit Freight — Expansion" (Qualification, 27000) and "Lakeview Retail — Ecommerce dashboards" (Needs Analysis, 52000) |
| Campaign | `701000000000001AAA` | "Ridgeway Robotics Q4 pilot", advertisement, in progress, budget 12000, actual cost 3400 |
| Campaign | `701000000000002AAA` | "Healthcare analytics webinar", completed, budget 4000, actual cost 3800 |
| CampaignMember | `00v000000000001AAA`, `00v000000000002AAA` | Erin Walsh in the Q4 pilot and Nora Bell in the webinar, both "Responded" |

The Helix account is hidden from queries, and direct reads and writes to it or its related records fail.

## Checks

Salesforce has no state checks. Use trace checks:

```yaml theme={null}
- id: updated_opportunity
  trace: { called: "PATCH /services/data/v67.0/sobjects/Opportunity/006000000000001AAA" }
- id: read_only
  trace: { not_called: ["POST /services/data/*", "PATCH /services/data/*", "DELETE /services/data/*"] }
```

## Limits

* Six objects; no Apex, triggers, workflows, lead conversion or assignment rules.
* No SOAP, Bulk API, OAuth flows or full Describe metadata.
* A simple per-account permission rule, not Salesforce's sharing model.


## Related topics

- [Worlds](https://docs.ancha.io/concepts/worlds.md)
- [Gong](https://docs.ancha.io/tools/gong.md)
- [Tools](https://docs.ancha.io/tools/overview.md)
- [Test file (scene.yaml)](https://docs.ancha.io/reference/test-file.md)
- [Introduction](https://docs.ancha.io/index.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.