Apideck Python SDK Skill
Overview
The Apideck Unified API provides a single integration layer to connect with 200+ third-party services across accounting, CRM, HRIS, file storage, ATS, e-commerce, and more. The official Python SDK (apideck-unify) provides typed clients for all unified APIs.
Installation
pip install apideck-unify
Requires Python 3.9+. Dependencies: httpx, pydantic.
IMPORTANT RULES
- ALWAYS use the
apideck-unifySDK. DO NOT make rawhttpx/requestscalls to the Apideck API. - ALWAYS pass
api_key,app_id, andconsumer_idwhen initializing the client. - ALWAYS set the
APIDECK_API_KEYenvironment variable rather than hardcoding API keys. - USE
service_idto specify which downstream connector to use (e.g.,"salesforce","quickbooks"). If a consumer has multiple connections for an API,service_idis required. - USE context managers (
with/async with) for client lifecycle management. - USE the
fieldsparameter to request only the columns you need. - USE the
filter_parameter (note the trailing underscore) to narrow results server-side. - ALWAYS handle errors with try/except using
models.ApideckErroras the base class.
Quick Start
from apideck_unify import Apideck
import os
with Apideck(
api_key=os.getenv("APIDECK_API_KEY", ""),
app_id="your-app-id",
consumer_id="your-consumer-id",
) as apideck:
res = apideck.crm.contacts.list(
service_id="salesforce",
limit=20,
filter_={"email": "john@example.com"},
)
while res is not None:
for contact in res.data:
print(contact.name, contact.emails)
res = res.next()
SDK Patterns
Client Setup
from apideck_unify import Apideck
import os
with Apideck(
api_key=os.getenv("APIDECK_API_KEY", ""),
app_id="your-app-id",
consumer_id="your-consumer-id",
) as apideck:
# Make API calls here
pass
The consumer_id identifies the end-user whose connections are being used. In multi-tenant apps, set this per-request or per-user session.
CRUD Operations
All resources follow the same pattern: apideck.{api}.{resource}.{operation}().
import apideck_unify
from apideck_unify import Apideck
import os
with Apideck(
api_key=os.getenv("APIDECK_API_KEY", ""),
app_id="your-app-id",
consumer_id="your-consumer-id",
) as apideck:
# LIST - retrieve multiple records
res = apideck.crm.contacts.list(
service_id="salesforce",
limit=20,
filter_={"email": "john@example.com", "company_id": "12345"},
sort={"by": apideck_unify.ContactsSortBy.CREATED_AT, "direction": apideck_unify.SortDirection.DESC},
fields="id,name,email",
)
# CREATE - create a new record
res = apideck.crm.contacts.create(
service_id="salesforce",
first_name="John",
last_name="Doe",
emails=[{"email": "john@example.com", "type": apideck_unify.EmailType.PRIMARY}],
phone_numbers=[{"number": "+1234567890", "type": apideck_unify.PhoneNumberType.PRIMARY}],
)
print(res.create_contact_response)
# GET - retrieve a single record
res = apideck.crm.contacts.get(id="contact_123", service_id="salesforce")
# UPDATE - modify an existing record
res = apideck.crm.contacts.update(id="contact_123", service_id="salesforce", first_name="Jane")
# DELETE - remove a record
res = apideck.crm.contacts.delete(id="contact_123", service_id="salesforce")
Pagination
Use the .next() method on response objects for cursor-based pagination:
res = apideck.accounting.invoices.list(service_id="quickbooks", limit=50)
while res is not None:
for invoice in res.data:
print(invoice.number, invoice.total)
res = res.next()
Async Support
Every sync method has an _async counterpart. Use async with as context manager:
import asyncio
from apideck_unify import Apideck
import os
async def main():
async with Apideck(
api_key=os.getenv("APIDECK_API_KEY", ""),
app_id="your-app-id",
consumer_id="your-consumer-id",
) as apideck:
res = await apideck.crm.contacts.list_async(
service_id="salesforce",
limit=20,
)
while res is not None:
for contact in res.data:
print(contact.name)
res = res.next()
asyncio.run(main())
Error Handling
from apideck_unify import Apideck, models
try:
res = apideck.crm.contacts.get(id="invalid", service_id="salesforce")
except models.BadRequestResponse as e:
print("Bad request:", e.message, e.status_code)
except models.UnauthorizedResponse as e:
print("Invalid API key or missing credentials")
except models.NotFoundResponse as e:
print("Record not found")
except models.PaymentRequiredResponse as e:
print("API limit reached")
except models.UnprocessableResponse as e:
print("Validation error:", e.message)
except models.ApideckError as e:
print(f"API error {e.status_code}: {e.message}")
All exceptions inherit from models.ApideckError with properties: message, status_code, headers, body, raw_response.
Common Parameters
| Parameter | Type | Description |
|---|---|---|
service_id | str | Downstream connector ID (e.g., "quickbooks", "salesforce") |
limit | int | Max results per page (1-200, default 20) |
cursor | str | Pagination cursor from previous response |
filter_ | dict | Resource-specific filter criteria (note trailing underscore) |
sort | dict | {"by": SortField, "direction": SortDirection} |
fields | str | Comma-separated field names to return |
pass_through | dict | Pass-through query parameters for the downstream API |
raw | bool | Include raw downstream response when True |
retry_config | RetryConfig | Per-call retry override |
Pass-Through Parameters
# Query pass-through
res = apideck.accounting.invoices.list(
service_id="quickbooks",
pass_through={"search": "overdue"},
)
# Body pass-through for connector-specific fields
res = apideck.crm.contacts.create(
service_id="salesforce",
first_name="John",
last_name="Doe",
pass_through=[{
"service_id": "salesforce",
"operation_id": "contactsAdd",
"extend_object": {"custom_sf_field__c": "value"},
}],
)
Retry Configuration
from apideck_unify import Apideck
from apideck_unify.utils import BackoffStrategy, RetryConfig
with Apideck(
api_key=os.getenv("APIDECK_API_KEY", ""),
app_id="your-app-id",
consumer_id="your-consumer-id",
retry_config=RetryConfig("backoff", BackoffStrategy(1, 50, 1.1, 100), False),
) as apideck:
pass
API Namespaces
| Namespace | Resources |
|---|---|
apideck.accounting.* | invoices, bills, payments, customers, suppliers, ledger_accounts, journal_entries, tax_rates, credit_notes, purchase_orders, balance_sheet, profit_and_loss, expenses, attachments, and more |
apideck.crm.* | contacts, companies, leads, opportunities, activities, notes, pipelines, users |
apideck.hris.* | employees, companies, departments, payrolls, time_off_requests |
apideck.file_storage.* | files, folders, drives, shared_links, upload_sessions |
apideck.ats.* | applicants, applications, jobs |
apideck.vault.* | connections, consumers, sessions, custom_mappings, logs |
apideck.webhook.* | webhooks, event_logs |