Skip to main content

Jamm API Python SDK

Project description

Jamm SDK for Python

Lightweight Python client for the Jamm API. Focused on:

  • Straightforward auth (client credentials OAuth2)
  • Clean dict responses (flattened where practical)
  • Helpful error metadata (error_type, error_code, decoded debug values)
  • Simple pagination (lazy charge iterator)

Installation

Production (when published):

pip install jamm-sdk

Local development (editable):

pip install -e .

Quick Start

import jamm

client = jamm.configure(
    client_id="your_client_id",
    client_secret="your_client_secret",
    env="develop",  # or "staging" / "production"
)

print(client.healthcheck())

Configuration

The SDK can be configured using environment variables or programmatically:

Programmatic Configuration

from jamm import JammClient, ClientConfig

config = ClientConfig(
    api_base_url="https://api.staging.jamm.com/v1",
    client_id="your_client_id",
    client_secret="your_client_secret"
)

client = JammClient(config)

Features Overview

Domain Highlights
Healthcheck Ping connectivity quickly
Customers CRUD + contract; normalized: link_initialized, bank_information, status
Payments On-session / off-session flows
Contracts Fetch existing customer contract
Charges Get, list, lazy iterator charges.iter()
Banking Bank search, major banks, branches (get/search/list)
Errors Unified ApiError with rich metadata

API Reference

Health Check

# Verify API connectivity
response = client.healthcheck()
print(response)

Customer Management

buyer_data = {
    "email": "customer@example.com",
    "name": "John Doe",
    "katakana_last_name": "ドウ",
    "katakana_first_name": "ジョン",
    "address": "123 Tokyo Street, Shibuya",
    "birth_date": "1990-01-01",
    "gender": "male",
    "force_kyc": False,
    "metadata": {"source": "api"}
}

customer = client.customers.create(buyer=buyer_data)
print(customer["id"])  # flattened
customer = client.customers.get("cus-customer_id_here")
updated = client.customers.update(
    customer_id="cus-customer_id_here",
    data={"name": "Updated Name", "metadata": {"updated": True}},
)
contract = client.customers.get_contract("cus-customer_id_here")
delete_result = client.customers.delete("cus-customer_id_here")

Payment Processing

from datetime import datetime, timedelta
expires_at = (datetime.now() + timedelta(days=2)).isoformat() + "Z"

off_session = client.payments.off_session(
    customer_id="cus-customer_id_here",
    price=1000,
    description="Monthly subscription",
    expires_at=expires_at,
)

on_session = client.payments.on_session(
    customer_id="cus-customer_id_here",
    price=1000,
    description="One-time payment",
    redirect_urls={
        "success_url": "https://yoursite.com/success",
        "failure_url": "https://yoursite.com/cancel",
    },
    expires_at=expires_at,
)

new_customer_session = client.payments.on_session(
    buyer=buyer_data,
    redirect_urls={
        "success_url": "https://yoursite.com/success",
        "failure_url": "https://yoursite.com/cancel",
    },
    expires_at=expires_at,
)

new_customer_with_charge = client.payments.on_session(
    buyer=buyer_data,
    price=1000,
    description="Initial payment",
    redirect_urls={
        "success_url": "https://yoursite.com/success",
        "failure_url": "https://yoursite.com/cancel",
    },
    expires_at=expires_at,
)

Contract Management

contract = client.contracts.get("cus-customer_id_here")
if contract:
    print("Contract found")
else:
    print("No active contract")

Charge Operations

charge = client.charges.get("trx-charge_id_here")
page = client.charges.list(customer_id="cus-customer_id_here", page_size=25)
for c in client.charges.iter(customer_id="cus-customer_id_here", page_size=100, limit=500):
    process(c)

Banking Operations

bank = client.banks.get("0001")
major_banks = client.banks.get_major_banks()
search_results = client.banks.search("みずほ")
branch = client.bank_branches.get("0001", "001")
branches = client.bank_branches.search("0001", "東京")
all_branches = client.bank_branches.list_for_bank("0001")

Authentication

OAuth2 client credentials handled automatically once configured.

Development Setup

python -m venv venv
source venv/bin/activate
pip install -e .

Running Tests

python tests/test_sdk.py --client-id YOUR_ID --client-secret YOUR_SECRET --env develop

Abbreviated example output:

✅ Healthcheck ok
✅ Customer created
✅ Off-session payment created
✅ On-session payment created
✅ Major banks fetched

Helper: generate_buyer()

from faker import Faker
import time

def generate_buyer(base_email=None, name=None, force_kyc=False):
    """Generate realistic buyer data for testing"""
    fake_en = Faker("en_US")
    fake_jp = Faker("ja_JP")
    timestamp = int(time.time())

    return {
        "email": f"{fake_en.user_name()}+{timestamp}@jamm-pay.jp",
        "name": name or fake_en.name(),
        "katakana_last_name": fake_jp.last_kana_name(),
        "katakana_first_name": fake_jp.first_kana_name(),
        "address": fake_jp.address(),
        "birth_date": fake_en.date_of_birth(minimum_age=20, maximum_age=70).strftime("%Y-%m-%d"),
        "gender": fake_en.random_element(["male", "female"]),
        "force_kyc": force_kyc,
        "metadata": {"source": "faker_generated", "timestamp": str(timestamp)}
    }

# Usage
buyer_data = generate_buyer()
customer = client.customers.create(buyer=buyer_data)

Error Handling

Every failed SDK call raises jamm.ApiError.

Field Meaning
code HTTP status (0 = network/transport)
message Short description
details Parsed JSON body
error_type Internal debug enum-like (e.g. ERROR_TYPE_PAYMENT_CHARGE_FAILED)
error_code High-level code (internal, invalid, etc.)
debug_values All collected debug markers
decoded_values Base64-decoded detail values
from jamm import ApiError
try:
    client.charges.get("trx-nonexistent")
except ApiError as e:
    print(e.code, e.message, e.error_type)
    if e.error_code:
        print("error_code:", e.error_code)
    if e.decoded_values:
        print("decoded:", e.decoded_values)

Network issues surface with code == 0 and details containing {"network_error": True}.

Notes & Next Steps

Planned (non-breaking): enum wrapper for error_type, helper predicates, optional typed response models. Contributions welcome.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jamm-0.3.0.tar.gz (84.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jamm-0.3.0-py3-none-any.whl (38.5 kB view details)

Uploaded Python 3

File details

Details for the file jamm-0.3.0.tar.gz.

File metadata

  • Download URL: jamm-0.3.0.tar.gz
  • Upload date:
  • Size: 84.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.4

File hashes

Hashes for jamm-0.3.0.tar.gz
Algorithm Hash digest
SHA256 754fdd2356468c10f9253fd657f62a09ed453d4ee26f88d1ca7fd4085888f63a
MD5 5f3f8ea1486b9d0eed0088f1a8f36708
BLAKE2b-256 4f868276d184caed2053f6db322d9729fbc7f076f087e82c7b86f7cedd1a0b4a

See more details on using hashes here.

File details

Details for the file jamm-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: jamm-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 38.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.4

File hashes

Hashes for jamm-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e6d6f946cbd389a9789c873c45825cc1918329db29ba2452d6dbcce61ad0e36b
MD5 99b84fca234bc663e21a569834fee89e
BLAKE2b-256 034f10dc0e822c0adbc08fb4ed63d3e8f86d1aa0168992f1f227a78468c64ace

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page