Salesforce · Arazzo Workflow

Salesforce Bulk Upsert Records

Version 1.0.0

Run the full Bulk API 2.0 upsert lifecycle — create an upsert ingest job keyed on an external Id field, upload CSV, close, poll, and read successful results.

1 workflow 2 source APIs 1 provider
View Spec View on GitHub Fortune 500Artificial IntelligenceAnalyticsCloudCommerceCRMCustomer ServiceEnterpriseMarketingPlatformSalesArazzoWorkflows

Provider

salesforce

Workflows

bulk-upsert-records
Bulk upsert records into a Salesforce object by external Id via the Bulk API 2.0 ingest lifecycle.
Creates an upsert ingest job keyed on an external Id field, uploads CSV data, closes the job, polls until JobComplete, and returns the successful results CSV.
5 steps inputs: csvData, externalIdFieldName, lineEnding, object outputs: jobId, numberRecordsFailed, numberRecordsProcessed, state, successfulResults
1
createJob
Create a new Bulk API 2.0 ingest job configured for the upsert operation against the target object, keyed on the supplied external Id field. The job starts in the Open state.
2
uploadData
Upload the CSV payload to the open ingest job. The header row must include the external Id field used for matching.
3
closeJob
Close the ingest job by setting its state to UploadComplete, which tells Salesforce to begin processing the upserts.
4
pollJob
Poll the ingest job state. When the job reaches JobComplete, continue to retrieve results; while still InProgress or UploadComplete, loop back to poll again; if the job Failed or Aborted, stop the workflow.
5
getResults
Retrieve the CSV of successfully processed records once the job has reached JobComplete. Each row includes the added sf__Id and sf__Created columns.

Source API Descriptions

Arazzo Workflow Specification

Raw ↑
arazzo: 1.0.1
info:
  title: Salesforce Bulk Upsert Records
  summary: Run the full Bulk API 2.0 upsert lifecycle — create an upsert ingest job keyed on an external Id field, upload CSV, close, poll, and read successful results.
  description: >-
    The Bulk API 2.0 ingest lifecycle for upserting many records at once,
    matching on an external Id field so each row is created or updated as
    needed. The workflow creates an upsert ingest job for a target object with
    the supplied externalIdFieldName, uploads the CSV payload, closes the job to
    begin processing, polls the job state until it reaches JobComplete
    (branching to retry while InProgress and to fail if the job reports Failed
    or Aborted), and finally retrieves the CSV of successfully processed
    records. Every step spells out its request inline so the flow can be read
    and executed without opening the underlying OpenAPI description.
  version: 1.0.0
sourceDescriptions:
- name: ingestJobDataApi
  url: ../openapi/salesforce-ingest-job-data-api-openapi.yml
  type: openapi
- name: ingestJobsApi
  url: ../openapi/salesforce-ingest-jobs-api-openapi.yml
  type: openapi
workflows:
- workflowId: bulk-upsert-records
  summary: Bulk upsert records into a Salesforce object by external Id via the Bulk API 2.0 ingest lifecycle.
  description: >-
    Creates an upsert ingest job keyed on an external Id field, uploads CSV
    data, closes the job, polls until JobComplete, and returns the successful
    results CSV.
  inputs:
    type: object
    required:
    - object
    - externalIdFieldName
    - csvData
    properties:
      object:
        type: string
        description: The API name of the SObject to upsert records into (e.g. Account).
      externalIdFieldName:
        type: string
        description: >-
          The API name of the external Id field used to match existing records
          for the upsert (e.g. External_Id__c).
      csvData:
        type: string
        description: >-
          CSV payload with a header row of field API names (including the
          external Id field) and one record per subsequent row.
      lineEnding:
        type: string
        description: Line ending used in the CSV data (LF or CRLF). Defaults to LF.
  steps:
  - stepId: createJob
    description: >-
      Create a new Bulk API 2.0 ingest job configured for the upsert operation
      against the target object, keyed on the supplied external Id field. The
      job starts in the Open state.
    operationId: createIngestJob
    requestBody:
      contentType: application/json
      payload:
        operation: upsert
        object: $inputs.object
        externalIdFieldName: $inputs.externalIdFieldName
        contentType: CSV
        lineEnding: $inputs.lineEnding
        columnDelimiter: COMMA
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      jobId: $response.body#/id
      state: $response.body#/state
  - stepId: uploadData
    description: >-
      Upload the CSV payload to the open ingest job. The header row must include
      the external Id field used for matching.
    operationId: uploadJobData
    parameters:
    - name: jobId
      in: path
      value: $steps.createJob.outputs.jobId
    requestBody:
      contentType: text/csv
      payload: $inputs.csvData
    successCriteria:
    - condition: $statusCode == 201
  - stepId: closeJob
    description: >-
      Close the ingest job by setting its state to UploadComplete, which tells
      Salesforce to begin processing the upserts.
    operationId: updateIngestJob
    parameters:
    - name: jobId
      in: path
      value: $steps.createJob.outputs.jobId
    requestBody:
      contentType: application/json
      payload:
        state: UploadComplete
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      state: $response.body#/state
  - stepId: pollJob
    description: >-
      Poll the ingest job state. When the job reaches JobComplete, continue to
      retrieve results; while still InProgress or UploadComplete, loop back to
      poll again; if the job Failed or Aborted, stop the workflow.
    operationId: getIngestJobInfo
    parameters:
    - name: jobId
      in: path
      value: $steps.createJob.outputs.jobId
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      state: $response.body#/state
      numberRecordsProcessed: $response.body#/numberRecordsProcessed
      numberRecordsFailed: $response.body#/numberRecordsFailed
    onSuccess:
    - name: jobComplete
      type: goto
      stepId: getResults
      criteria:
      - condition: $response.body#/state == "JobComplete"
    - name: stillProcessing
      type: goto
      stepId: pollJob
      criteria:
      - condition: $response.body#/state == "InProgress"
    onFailure:
    - name: jobFailed
      type: end
      criteria:
      - condition: $response.body#/state == "Failed"
  - stepId: getResults
    description: >-
      Retrieve the CSV of successfully processed records once the job has
      reached JobComplete. Each row includes the added sf__Id and sf__Created
      columns.
    operationId: getSuccessfulResults
    parameters:
    - name: jobId
      in: path
      value: $steps.createJob.outputs.jobId
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      successfulResults: $response.body
  outputs:
    jobId: $steps.createJob.outputs.jobId
    state: $steps.pollJob.outputs.state
    numberRecordsProcessed: $steps.pollJob.outputs.numberRecordsProcessed
    numberRecordsFailed: $steps.pollJob.outputs.numberRecordsFailed
    successfulResults: $steps.getResults.outputs.successfulResults

Work with this as data

Every workflow here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for arazzo workflows

4 MCP tools reach this
  • find_arazzoBrowse and filter every workflow in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This workflow
curl "https://apis.io/api/v1/arazzo/salesforce-bulk-upsert-records-workflow"
All arazzo workflows
curl "https://apis.io/api/v1/arazzo?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.