---
schema_version: "1"
id: c7c4fa81dde09453ff840f824ac69757435db6133cf7238c6ebb8230e37a60d1
title: "Step 2: Build the Python Client"
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/event-bus/pub-sub-api/guides/qs-build-python-client.md
canonical_url: https://developer.salesforce.com/docs/platform/pub-sub-api/guide/qs-build-python-client.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 2af5406609ae8efdc953f6e0a2722a119d91e17102ef819b1f8bfed2b476e480
products:
  - Pub/Sub API
  - Event Bus Docs
---
# Step 2: Build the Python Client

1. Create a Python file in any editor. For example, create a file named `PubSubAPIClient.py`.
2. To import these modules, add these import statements at the top of the file.

   ```
   import grpc
   import requests
   import threading
   import io
   import pubsub_api_pb2 as pb2
   import pubsub_api_pb2_grpc as pb2_grpc
   import avro.schema
   import avro.io
   import time
   import certifi
   import json
   ```

3. Set a semaphore at the beginning of the program.

   ```
   semaphore = threading.Semaphore(1)
   ```

   Because of Python gRPC’s design, the program shuts down immediately if no response comes back in the milliseconds between calling an RPC and the end of the program. When you set a semaphore, the client keeps running indefinitely. In this example, you define the semaphore globally. Because this sample starts one subscription via one Subscribe RPC call, the global semaphore works. However, the global semaphore isn’t appropriate for multiple subscriptions because the semaphore is shared. If you change this sample code to make multiple Subscribe RPC calls, make sure that each Subscribe call uses a separate semaphore and the semaphore isn’t shared among subscriptions.

4. Create a global variable to store the replay ID.

   ```
   latest_replay_id = None
   ```

5. Set up the gRPC channel, and generate the stub. The gRPC channel points to the Pub/Sub API endpoint `api.pubsub.salesforce.com:7443`. In this quick start, we use port `7443`, but you can alternatively use port `443`. If your company uses a firewall for network security, make sure that the Pub/Sub API endpoint is allowed in the firewall configuration.

   ```
   with open(certifi.where(), 'rb') as f:
       creds = grpc.ssl_channel_credentials(f.read())
   with grpc.secure_channel('api.pubsub.salesforce.com:7443', creds) as channel:
       # All of the code in the rest of the tutorial will go inside this block.
       # Make sure that the indentation of the new code you add starts from this comment’s block.
   ```

6. Retrieve your session token. Replace the username, password, and API login URL with values for your Salesforce org. Replace `MyDomainName` with your org’s My Domain name. For more information, see [My Domain URL Formats
   ](https://help.salesforce.com/s/articleView?id=xcloud.domain_name_app_url_changes.htm&type=5) in _Salesforce Help_. If you’re using a production instance, the API login URL is `https://MyDomainName.my.salesforce.com/services/Soap/u/59.0/`. If it’s a sandbox, the URL is `https://MyDomainName--SandboxName.sandbox.my.salesforce.com/services/Soap/u/59.0/`. Send a POST request formatted like this to the login URL.

   ```
   username = '{your username}'
   password = '{your password}'
   url = '{the appropriate login URL}'
   headers = {'content-type': 'text/xml', 'SOAPAction': 'login'}
   xml = f"""<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
   xmlns:urn='urn:partner.soap.sforce.com'><soapenv:Body>
   <urn:login>
   <urn:username><![CDATA[{username}]]></urn:username>
   <urn:password><![CDATA[{password}]]></urn:password>
   </urn:login></soapenv:Body></soapenv:Envelope>"""
   res = requests.post(url, data=xml, headers=headers, verify=False)
   #Optionally, print the content field returned
   print(res.content)
   ```

   **note:** - When you copy the code snippet, ensure that it aligns with the indented block of code above it. In Python, code blocks are delimited by their indentation.
   - If you haven’t set up a range of trusted IP addresses for your org, append a security token to your password. For more information, see [Reset Your Security Token](https://help.salesforce.com/s/articleView?id=xcloud.user_security_token.htm&type=5) and [Set Trusted IP Ranges for Your Org](https://help.salesforce.com/s/articleView?id=xcloud.security_networkaccess.htm&type=5).
   - The code example uses username and password authentication for simplicity, but we recommend that you use OAuth in production apps. For more information, see [Supported Authentication](https://developer.salesforce.com/docs/platform/pub-sub-api/guide/supported-auth.md).

7. Run this client by entering this command on the command line.

   ```
   python3 PubSubAPIClient.py
   ```

   When the request returns, you have XML-formatted data in the response content field `res.content`. It contains a session ID wrapped within the `<sessionId>` tags. It also contains the server URL wrapped within the `<serverUrl>` tags and the org ID within the `<organizationId>` tags under `<userInfo>`. Note those values because you use them in the next step.

   **note:** After getting the session information, you can delete or comment out the login code you added in the previous step. To comment out a line in Python, prepend it with `#`.

8. Store the authorization information, including session ID, instance URL, and org ID, in a tuple called `authmetadata`. Each element in this tuple is also a tuple. You use this information when subscribing to a channel or publishing events.

   1. Replace the `sessionid` placeholder value with the session ID that you got from the previous step.
   2. Replace the `instanceurl` placeholder value with the first part of the server URL that you got from the previous step, without the path portion. For example, `https://MyDomainName.my.salesforce.com`.
   3. Replace the `tenantid` placeholder value with the org ID that you got from the previous step. For more information about the headers, see [Include Authorization Headers in RPC Method Calls](https://developer.salesforce.com/docs/platform/pub-sub-api/references/methods/rpc-method-headers.html).

      ```
      sessionid = '{the session ID you just got from the XML}'
      instanceurl = '{the first part of the server URL ending in .com}'
      tenantid = '{organization ID}'
      authmetadata = (('accesstoken', sessionid),
      ('instanceurl', instanceurl),
      ('tenantid', tenantid))
      ```

9. Generate your stub object like this. `PubSubStub` comes from the `pubsub_api_pb2_grpc.py` file, which you generated in the previous step.

   ```
   stub = pb2_grpc.PubSubStub(channel)
   ```
