Salesforce

Lightweight, dependency-free, in-memory fake of the Salesforce REST API (v59.0) for testing code that uses jsforce or the Salesforce REST API directly.

Default port: 4778

Quick start

import { SalesforceServer } from "./services/salesforce/src/server.js";

const server = new SalesforceServer(4778);
await server.start();
// ... run your app/tests ...
await server.stop();

Point a client at it:

const base = "http://127.0.0.1:4778";
const res = await fetch(`${base}/services/data/v59.0/sobjects/Account`, {
  method: "POST",
  headers: { Authorization: "Bearer pat-parlel", "Content-Type": "application/json" },
  body: JSON.stringify({ Name: "Parlel Inc" }),
});
// => { id, success: true, errors: [] }

Access via MCP / preview URL

Plain HTTP at http://127.0.0.1:4778, reachable through the parlel MCP/preview proxy under the slug salesforce.

Implemented operations

All /services/data/* routes require Authorization: Bearer <token> (any non-empty bearer works). State is in-memory and ephemeral. Record ids are 18 chars with the standard key prefix per object (001 Account, 003 Contact, 00Q Lead, 006 Opportunity, 500 Case).

sObjects — /services/data/v59.0/sobjects/:Object

Query — /services/data/v59.0/query

Service & inspection operations (parlel extensions)

Surface coverage

This emulator faithfully replicates the API surface most application code and agents exercise. Anything below the supported lines is either an intentional design choice for a fast, zero-cost local emulator (✓ By design) or a candidate for a future release (⟳ Roadmap) — never a silent inaccuracy.

Legend: ✅ fully supported · ◐ accepted (stored, not strictly enforced) · ✓ by design · ⟳ on the roadmap.

FeatureStatus
sObject create / retrieve / update / delete✅ Supported
SOQL query (FROM, single WHERE field = 'value')✅ Supported
{id,success,errors} create envelope✅ Supported
Required-field validation (standard objects)✅ Supported — REQUIRED_FIELD_MISSING
Retrieve ?fields= projection✅ Supported
Arbitrary / custom object types◐ Accepted (no schema, not enforced)
Composite / bulk / tree APIs⟳ Roadmap
Full SOQL (joins, aggregates, ORDER BY, LIMIT, relationships)◐ Minimal subset
Describe / metadata APIs⟳ Roadmap
OAuth token validity / org boundaries✓ By design — Any non-empty credential is accepted — no real secrets needed

Error codes & shapes

Errors use the Salesforce array envelope [{ message, errorCode }].

StatuserrorCodeWhen
400REQUIRED_FIELD_MISSINGa required field is missing on a standard-object create (includes a fields array)
400MALFORMED_QUERY / JSON_PARSER_ERRORbad SOQL / malformed JSON
401INVALID_SESSION_IDno Authorization: Bearer header
404NOT_FOUNDunknown record / endpoint
405METHOD_NOT_ALLOWEDmethod not allowed for the path

Manifest

See services/salesforce/manifest.json: name salesforce, port 4778, protocol http, healthcheck /health, startup ≈ 100ms, env SALESFORCE_ACCESS_TOKEN, SALESFORCE_BASE_URL.

<!-- parlel:testenv:start -->

Configuration — test.env

Copy these into your test.env (used by the bridge sidecar flow). Tokens are Parlel's seeded test credentials — any non-empty value is accepted by the emulator, so you rarely need to change them. Swap in real credentials only when pointing at the live service in prod.env.

SALESFORCE_ACCESS_TOKEN=pat-parlel
SALESFORCE_BASE_URL=http://parlel-bridge:4778
<!-- parlel:testenv:end -->