{"id":2273,"library":"salesforce-bulk","title":"Salesforce Bulk API Client","description":"A Python interface to the Salesforce.com Bulk API, enabling efficient, asynchronous processing of large data sets for insert, update, upsert, and delete operations. The current version is 2.2.0, with a release cadence that has seen updates in 2023 and 2024, indicating active maintenance.","status":"active","version":"2.2.0","language":"en","source_language":"en","source_url":"https://github.com/heroku/salesforce-bulk","tags":["salesforce","api","bulk","crm","data-integration"],"install":[{"cmd":"pip install salesforce-bulk","lang":"bash","label":"Install salesforce-bulk"}],"dependencies":[],"imports":[{"symbol":"SalesforceBulk","correct":"from salesforce_bulk import SalesforceBulk"},{"note":"Useful for checking job statuses like 'Closed', 'Aborted', 'Failed'.","symbol":"BulkJobState","correct":"from salesforce_bulk import BulkJobState"},{"note":"Useful for checking batch statuses like 'Queued', 'InProgress', 'Completed', 'Failed'.","symbol":"BulkBatchState","correct":"from salesforce_bulk import BulkBatchState"}],"quickstart":{"code":"import os\nimport time\nfrom salesforce_bulk import SalesforceBulk, BulkJobState, BulkBatchState\n\n# Configure Salesforce credentials using environment variables\nSF_USERNAME = os.environ.get('SF_USERNAME', 'your_sf_username')\nSF_PASSWORD = os.environ.get('SF_PASSWORD', 'your_sf_password')\nSF_SECURITY_TOKEN = os.environ.get('SF_SECURITY_TOKEN', 'your_sf_security_token')\nSF_INSTANCE_URL = os.environ.get('SF_INSTANCE_URL', 'https://your_instance.my.salesforce.com') # Optional, if using My Domain\n\nif SF_USERNAME == 'your_sf_username':\n    print(\"WARNING: Please set SF_USERNAME, SF_PASSWORD, and SF_SECURITY_TOKEN environment variables.\")\n    print(\"Skipping quickstart execution.\")\nelse:\n    try:\n        # Initialize SalesforceBulk client\n        # For Sandbox/Production, usually username/password/security_token is sufficient.\n        # For My Domain or specific instances, instance_url might be needed.\n        sf_bulk = SalesforceBulk(\n            username=SF_USERNAME,\n            password=SF_PASSWORD,\n            security_token=SF_SECURITY_TOKEN,\n            instance_url=SF_INSTANCE_URL # Optional, if not using My Domain or standard instance\n        )\n\n        # Example: Create an 'Account' insert job\n        job = sf_bulk.create_job(object_name='Account', operation='insert')\n        print(f\"Created Bulk Job: {job['id']}\")\n\n        # Prepare data (list of dictionaries)\n        accounts_data = [\n            {'Name': 'Test Account 1', 'Industry': 'Technology'},\n            {'Name': 'Test Account 2', 'Industry': 'Healthcare'}\n        ]\n\n        # Add a batch to the job\n        batch = sf_bulk.post_batch(job_id=job['id'], data=accounts_data)\n        print(f\"Posted Batch: {batch['id']}\")\n\n        # Close the job (important: no more batches can be added after this)\n        sf_bulk.close_job(job_id=job['id'])\n        print(f\"Closed Bulk Job: {job['id']}\")\n\n        # Poll for job and batch status (Bulk API is asynchronous)\n        print(\"Polling for job and batch completion...\")\n        while True:\n            job_status = sf_bulk.get_job_info(job_id=job['id'])\n            batch_status = sf_bulk.get_batch_info(job_id=job['id'], batch_id=batch['id'])\n            print(f\"Job State: {job_status['state']}, Batch State: {batch_status['state']}\")\n\n            if job_status['state'] == BulkJobState.CLOSED and batch_status['state'] in [BulkBatchState.COMPLETED, BulkBatchState.FAILED]:\n                break\n            time.sleep(5) # Wait for 5 seconds before re-polling\n\n        if batch_status['state'] == BulkBatchState.COMPLETED:\n            print(\"Batch completed successfully!\")\n            # Retrieve results\n            results = sf_bulk.get_batch_results(job_id=job['id'], batch_id=batch['id'])\n            print(\"Batch Results:\")\n            for res in results:\n                print(f\"  Success: {res['success']}, Id: {res['id']}, Error: {res.get('errors')}\")\n        else:\n            print(f\"Batch failed with state: {batch_status['state']}\")\n            print(f\"Job failures: {job_status.get('numberRecordsFailed')}\")\n            print(f\"Batch errors: {sf_bulk.get_batch_results(job_id=job['id'], batch_id=batch['id'])}\")\n\n    except Exception as e:\n        print(f\"An error occurred: {e}\")","lang":"python","description":"This quickstart demonstrates how to connect to Salesforce using `SalesforceBulk`, create an 'insert' job for 'Account' objects, post a batch of data, close the job, and then poll for its completion. It also shows how to retrieve results from completed batches. Remember that the Salesforce Bulk API is asynchronous, so polling is necessary."},"warnings":[{"fix":"Review any custom network configurations or error parsing that interact directly with the HTTP client. Ensure `requests` is installed and accessible. For most common use cases, no code change is required for basic API calls.","message":"Version 2.0.0 changed the underlying HTTP client from `httplib` to `requests`. While the public `SalesforceBulk` interface largely remained the same, custom HTTP client configurations, lower-level network interactions, or error handling dependent on `httplib` might break.","severity":"breaking","affected_versions":"1.x.x to 2.0.0+"},{"fix":"Always poll the `get_job_info()` and `get_batch_info()` methods, checking their 'state' attributes, until the job/batch is in a final state (e.g., `BulkJobState.CLOSED`, `BulkBatchState.COMPLETED` or `BulkBatchState.FAILED`).","message":"The Salesforce Bulk API is asynchronous. Jobs and batches do not complete immediately. It is crucial to implement polling mechanisms to check job and batch statuses before attempting to retrieve results or assuming completion.","severity":"gotcha","affected_versions":"All"},{"fix":"Always process large datasets in appropriately sized chunks. For very large files, split them into multiple batches, each within Salesforce's documented limits, and post them to the same job.","message":"Incorrect batch sizing can lead to API limits or performance issues. Salesforce has limits on batch sizes (e.g., 10,000 records or 10MB). Exceeding these limits for a single batch will result in errors.","severity":"gotcha","affected_versions":"All"},{"fix":"Ensure the correct Salesforce security token is appended to the password (if applicable) or passed as a separate `security_token` argument. For My Domain instances, explicitly providing `instance_url` can also be beneficial.","message":"Security tokens are often required when connecting to Salesforce via username/password from untrusted IP ranges or without an active session. Forgetting it or providing an invalid one will lead to authentication failures.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}