Metadata-Version: 2.5
Name: merofoundry-client
Version: 0.1.0
Summary: Async Python client for the MeroFoundry platform API.
Project-URL: Homepage, https://merofoundry.com
Project-URL: Documentation, https://docs.merofoundry.app
License: MIT License
        
        Copyright (c) 2026 Mero Consulting
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# merofoundry-client

Async Python client for the [MeroFoundry](https://merofoundry.com) public API.

MeroFoundry is a platform for building applications — data models, forms, pages and rules — and
this library is the typed, `httpx`-based way to drive one from Python. It is the same client the
[`merofoundry-mcp`](https://pypi.org/project/merofoundry-mcp/) server is built on.

## Install

```bash
pip install merofoundry-client
```

Requires Python 3.11 or newer.

## Quick start

The client is asynchronous and is an async context manager, so the underlying connection pool is
closed for you:

```python
import asyncio
import os

from merofoundry_client import MeroFoundryClient

APP_ID = "..."
MODEL_ID = "..."


async def main() -> None:
    async with MeroFoundryClient(
        "https://platform.merofoundry.com",
        api_key=os.environ["MEROFOUNDRY_API_KEY"],
    ) as client:
        app = await client.get_application(APP_ID)
        print(app["name"])

        page = await client.list_records(APP_ID, MODEL_ID, per_page=50)
        print(page["total"], "records")
        for record in page["items"]:
            print(record["id"], record["data"])

        created = await client.create_record(
            APP_ID, MODEL_ID, data={"title": "Hello"}, idempotency_key="hello-1"
        )
        print(created["id"])


asyncio.run(main())
```

Pass the API base URL as the host root — `https://platform.merofoundry.com`, not a path. The client
appends the public API prefix itself.

## Authentication

Authentication is an API key, sent as `X-API-Key`. Keys are scoped to a single application and
carry only the permissions granted to them, so a data-plane key that can read and write records
cannot create models or delete an application. Authoring keys are considerably more powerful;
treat them accordingly.

## Idempotency

Writes that create something accept an `idempotency_key`. Passing one makes a retry safe — the
same key returns the original record rather than creating a second one. Use it anywhere a network
error could otherwise leave you unsure whether a write landed.

## Errors

Every failure raises a subclass of `MeroFoundryError`, so one `except` clause covers the library:

```python
from merofoundry_client import (
    MeroFoundryError,      # base class for everything below
    AuthError,             # missing or invalid key
    PermissionDeniedError, # key lacks the permission
    CapabilityError,       # the application does not offer this capability
    NotFoundError,
    ConflictError,
    ValidationError,
    StorageError,
    RateLimitError,
    ApiError,              # anything else the API returned
)

try:
    await client.get_record(APP_ID, MODEL_ID, record_id)
except NotFoundError:
    ...
except MeroFoundryError as exc:
    # exc carries the API's own code, HTTP status and message
    print(exc)
```

A transport failure — DNS, connection refused, timeout — also arrives as a `MeroFoundryError`
rather than a raw `httpx` exception, so callers do not have to catch two families.

## What it covers

41 methods across the public API:

| Area | Methods |
|---|---|
| Applications | `get_application`, `create_application`, `update_application`, `delete_application` |
| Models and fields | `list_models`, `get_model`, `create_model`, `update_model`, `delete_model`, `publish_model`, `add_field`, `update_field`, `delete_field` |
| Records | `list_records`, `get_record`, `search_records`, `create_record`, `update_record`, `delete_record` |
| Files | `upload_file`, `get_file`, `download_file`, `delete_file` |
| Pages | `create_page`, `list_pages`, `get_page`, `update_page`, `delete_page`, `render_page`, `get_published_page` |
| Forms | `create_form`, `update_form`, `delete_form` |
| Rules and services | `create_rule`, `test_rule`, `run_rule_event`, `run_saved_query`, `invoke_service`, `invoke_service_stream`, `set_outbound_governance` |

A model must be **published** before records can be created against it. Adding or changing a field
returns the model to draft, so re-publish after schema changes.

## Status

`0.1.0`, pre-1.0. The API surface may still change between minor versions.
