Developers
Build with the Python library
A ten-minute walkthrough: list your clients, read a client's Google Sheet, type their services, and handle a client who needs to reconnect.
Shane Arcaro
Build with the Python library
On this page
Operate As works from AI agents over MCP, from n8n, and from plain HTTPS. When you're writing your own code, our libraries for Python, TypeScript and Go make it shorter: every service comes as a typed package, every error has a name, and your clients' tokens never touch your code.
This walkthrough uses the Python library. In about ten minutes you'll list your clients, read rows from a client's Google Sheet, and handle a client who needs to reconnect.
Before you start
You need an Operate As account with at least one client who has connected a service. Then create an API key on the dashboard's API & webhooks page. You can limit it to specific clients, services and actions, and it's shown only once, so keep it somewhere safe.
Store the key in an environment variable rather than in your code:
export OPERATE_AS_API_KEY="oa_..."
Install
The library needs Python 3.9 or newer and has no dependencies beyond the standard library. Each service has a typed package of its own, such as operate-as-sheets, with every action as a method. Install the library and the services you use:
pip install operate-as operate-as-sheets operate-as-slack
With uv, it's uv add operate-as operate-as-sheets operate-as-slack, and with Poetry, poetry add the same packages.
List your clients
Create one OperateAs with your key and reuse it everywhere. It's safe to share between threads.
import os
from operate_as import OperateAs
operate = OperateAs(os.environ["OPERATE_AS_API_KEY"])
for client in operate.clients.list():
print(client.id, client.name, client.services) # 6f1c2a7e-... Miller Dental ['sheets', 'slack']
You only see the clients your key can reach. To find the ones with a particular service connected, pass service.
Work in a client's accounts
Pick a client by their id, and hand them to each service's package:
from operate_as_sheets import Sheets
from operate_as_slack import Slack
client = operate.client("6f1c2a7e-...") # Miller Dental, with sheets and slack connected
rows = Sheets(client).read_rows(spreadsheet_id="1BxiM...", range="A1:D20")
Slack(client).send_message(channel="#front-desk", text=f"{len(rows.data['values'])} bookings today")
Operate As attaches the client's access on our server, calls Google and Slack, and hands back each service's own status and response. Your code never sees a token.
Every input is typed and documented, so your editor completes it and Pyright or mypy catches a misspelled one.
Each client only has the services they've connected. Call one they haven't, like HubSpot for a client without it, and you get a ReconnectRequiredError that says so. Use a client from operate.clients.list() and it's a NotConnectedError straight away, before anything is sent, naming the services they do have.
Call any endpoint
When a ready-made action doesn't cover what you need, call the service's own API directly. Give the path as the service documents it, and we add the client's access:
deal = operate.request(
"6f1c2a7e-...",
"hubspot",
"POST",
"/crm/v3/objects/deals",
body={"properties": {"dealname": "Spring campaign", "amount": "4200"}},
)
print(deal.status)
This needs only the library, so it works for every service, packaged or not.
Handle a client who needs to reconnect
Access can end when a client changes their password or removes it. Instead of failing quietly, the library raises ReconnectRequiredError, so you can tell your team or send the client their link. NotConnectedError is a kind of ReconnectRequiredError, so the same handler catches both:
import operate_as
try:
Sheets(client).add_row(spreadsheet_id="1BxiM...", range="A1", values=["2026-10-22", "Emma Carter"])
except operate_as.ReconnectRequiredError as error:
print(f"Miller Dental needs to reconnect: {error.detail}")
except operate_as.OperateAsError as error:
print(error.status, error.detail)
Every error carries a status and a detail written to be shown to a person.
Give agents short-lived keys
If an AI agent is calling Operate As, keep your main key on your server and hand each run a short-lived key instead. It reaches no more than your key, can be narrowed further, and stops working when it expires:
short = operate.keys.create_short_lived(expires_in=900, services=["sheets"])
agent = OperateAs(short.secret) # or use short.secret as the agent's MCP bearer token
What's next
- Hear about changes as they happen. Add a webhook on the API & webhooks page, and check each delivery with
Webhook.verifyfrom the library. - Using another language? The TypeScript and Go libraries work the same way, with the same key.
- Building with an AI agent? Point Claude, ChatGPT or Cursor at our MCP server, and it gets the same tools.
See every option on the developers page.