Easy Labs
SDKsPython

Type hints

Type-level conventions and exported types in easy-sdk (pip).

easylabs is fully typed. Public types are tested under pyright in standard mode and ship with the wheel via PEP 561 — no separate stubs package to install. If you use mypy, pyright, or any LSP that respects inline annotations, autocomplete and type checking just work.

The SDK targets Python >= 3.10 so it can use native X | None unions, PEP 604 syntax, and from __future__ import annotations throughout.

Response models — pydantic v2

Every method returns a pydantic v2 model (or a list/dict of them). Models inherit from easylabs.EasyModel, which sets:

  • extra="allow" — forward-compatible. New fields the API adds appear on the model and survive model_dump() round-trips.
  • populate_by_name=True — fields with Field(alias=...) accept both the alias and the snake_case name on construction.

That means:

customer = client.customers.retrieve("cus_123")

customer.id            # str
customer.email         # str | None
customer.tags          # dict[str, Any] | None
customer.model_dump()  # plain dict — useful for logging / DB insert

To go the other way (dict → model), use Customer.model_validate(...):

from easylabs import Customer

raw = {"id": "cus_123", "email": "ada@example.com"}
customer = Customer.model_validate(raw)

Public types

All of these are importable from the top-level easylabs package.

Client + errors

TypePurpose
ClientThe SDK entry point.
EasyErrorBase for every SDK error.
AuthenticationError401.
PermissionError403 (shadows the Python builtin).
NotFoundError404.
ConflictError409.
InvalidRequestError400 / 422.
RateLimitError429 (carries retry_after_seconds).
ServerError5xx.

Webhooks

TypePurpose
WebhooksStatic utility namespace; exposes construct_event(...).
WebhookEventVerified event payload (id, type, data, created_at).
EVENT_TYPESTuple of every event name the SDK knows about.

Resource models

Customer / billing / payments:

Customer, PaymentInstrument, FinixPaymentInstrument, Transfer, Authorization, Order, Settlement, Dispute, Wallet.

Catalog & subscriptions:

Product, ProductPrice, Subscription, SubscriptionItem, SubscriptionDiscount, SubscriptionPlan, Coupon, PromotionCode, ValidatePromotionCodeResponse.

Checkout:

CheckoutResponse, PaymentLink, CreatePaymentLinkResponse, EmbeddedCheckoutSession, EmbeddedCheckoutSessionStatus, EmbeddedCheckoutConfig, ValidateEmbeddedCheckoutSessionResponse, CryptoPaymentStatus.

Operations:

Invoice, DunningConfig, RevenueRecoveryAutomation, RevenueRecoveryAutomationRun, ComplianceForm, AnalyticsResult, WebhookEndpoint, RegisteredWebhookEndpoint, WebhookDelivery.

Treasury (importable from easylabs.models):

TreasuryBankAccount, TreasuryCategory, TreasuryRecipient, TreasuryTransaction, TreasuryPayoutLink, TreasuryRecurringPayment, TreasuryAutoTransferRule, TreasurySecurityRule, TreasuryApprovalRequest.

Extending models

Because EasyModel sets extra="allow", brand-new fields the API ships between SDK releases are still accessible — just not statically typed:

customer = client.customers.retrieve("cus_123")

# Statically-known field — type-checked.
print(customer.id)

# New field the SDK doesn't know about yet — accepted at runtime.
print(customer.model_extra.get("future_field"))

If you need stronger typing for an extra field across your codebase, subclass the model:

from easylabs import Customer

class TenantCustomer(Customer):
    tenant_id: str | None = None

raw = client.customers.retrieve("cus_123").model_dump()
tenant_customer = TenantCustomer.model_validate(raw)

On this page