This library provides basic functionality for building Python apps that use Heroku AppLink to secure communication and credential sharing with a Salesforce org.
Though the interaction with AppLink is simple and easy to hand code, using the SDK will quickstart your project experience.
Use of this project with Salesforce is subject to the TERMS_OF_USE.md document.
Documentation for the SDK is available and is generated from the source code.
Install the doc dependency group.
$ uv sync --group docs
Generate the documentation.
$ uv run pdoc3 --template-dir templates/python heroku_applink -o docs --force
-
Clone the repository:
git clone https://github.com/heroku/heroku-applink-python.git cd heroku-applink-python
-
Install Dependencies:
Install the
uv
package manager:curl -LsSf https://astral.sh/uv/install.sh | sh
Sync all dependencies:
uv sync --all-extras
-
Sync Development Dependencies:
uv sync --all-extras --dev
-
Run the full test suite:
# Run all tests uv run pytest # Run all tests with coverage uv run pytest --cov=heroku_applink.data_api --cov-report=term-missing -v
-
Run a single test:
# Run a specific test file uv run pytest <path_to_test_file>/test_specific_file.py # Run a specific test file with coverage uv run pytest tests/data_api/test_data_api_record.py::test_some_specific_case \ --cov=heroku_applink.data_api
-
Run tests with a specific Python version:
pyenv shell 3.12.2 # Or any installed version uv venv source .venv/bin/activate uv sync --all-extras --dev uv run pytest
-
Run tests across multiple Python versions with Tox:
uv sync --all-extras --dev uv run tox
-
Run the Ruff linter:
# Check the code for issues uv run ruff check . # Automatically fix issues uv run ruff check . --fix # Check a specific directory (e.g., heroku_applink) uv run ruff check heroku_applink/ # Format the codebase uv run ruff format .
For more detailed information about the SDK's capabilities, please refer to the full documentation.
Install the package.
$ uv pip install heroku_applink
Add the middleware to your web framework.
If you are using an ASGI framework (like FastAPI), you can use the IntegrationAsgiMiddleware
to automatically populate the client-context
in the request scope.
# FastAPI example
import asyncio
import heroku_applink as sdk
from fastapi import FastAPI
config = sdk.Config(request_timeout=5)
app = FastAPI()
app.add_middleware(sdk.IntegrationAsgiMiddleware, config=config)
@app.get("/")
def get_root():
return {"root": "page"}
@app.get("/accounts")
def get_accounts():
data_api = sdk.client_context.get().data_api
asyncio.run(query_accounts(data_api))
return {"Some": "Accounts"}
async def query_accounts(data_api):
query = "SELECT Id, Name FROM Account"
result = await data_api.query(query)
for record in result.records:
print("===== account record", record)
If you are using a WSGI framework (like Flask), you can use the IntegrationWsgiMiddleware
to automatically populate the client-context
in the request environment.
from flask import Flask, jsonify, request
import heroku_applink as sdk
config = sdk.Config(request_timeout=5)
app = Flask(__name__)
app.wsgi_app = sdk.IntegrationWsgiMiddleware(app.wsgi_app, config=config)
@app.route("/")
def index():
return jsonify({"message": "Hello, World!"})
@app.route("/accounts")
def get_accounts():
data_api = sdk.client_context.get().data_api
query = "SELECT Id, Name FROM Account"
result = data_api.query(query)
return jsonify({"accounts": [record.get("Name") for record in result.records]})
If you are not using a framework, you can manually extract the x-client-context
header and use the DataAPI
class to query the Salesforce org.
from heroku_applink.data_api import DataAPI
header = request.headers.get("x-client-context")
decoded = base64.b64decode(header)
data = json.loads(decoded)
data_api = DataAPI(
org_domain_url=data["orgDomainUrl"],
api_version=data["apiVersion"],
access_token=data["accessToken"],
)
result = data_api.query("SELECT Id, Name FROM Account")