Metadata-Version: 2.4
Name: MagicFeedback
Version: 1.0.17
Summary: SDK for MagicFeedback API
Home-page: https://github.com/MagicFeedback/magicfeedback_python_sdk
Author: Francisco Arias
Author-email: Francisco Arias <farias@magicfeedback.io>
Project-URL: Homepage, https://github.com/MagicFeedback/magicfeedback_python_sdk
Project-URL: Issues, https://github.com/MagicFeedback/magicfeedback_python_sdk/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENCE
Requires-Dist: requests>=2.0.0
Requires-Dist: google-cloud-pubsub>=2.0.0
Requires-Dist: google-cloud-datastore>=2.16.0
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# MagicFeedback Python SDK

Python SDK for the MagicFeedback API.

## Installation

```bash
pip install MagicFeedback
```

> Note: the distribution name on PyPI is `MagicFeedback`, but the import name is `magicfeedback_sdk`.

## Usage

```python
from magicfeedback_sdk import MagicFeedback

client = MagicFeedback("email", "password")
```

## Authentication

The bearer token is resolved from one of two sources, selected with
`auth_source`:

- `"datastore"` **(default)** — read the token cached in Google Cloud Datastore
  by the `update-token` job (kind `token-storage`, email
  `robot@magicfeedback.io`, database `shared`). This avoids an Identity Platform
  login on every use. If the cached token is missing, stale (older than
  `token_max_age_min`, default 50 min) or Datastore is unreachable, the client
  falls back to Identity Platform using `email`/`password`.
- `"identity"` — always log in via Identity Platform (`signInWithPassword`), the
  original behaviour, with no Datastore lookup.

```python
# Datastore-cached token (default), with Identity Platform fallback.
# email/password are only needed for the fallback.
client = MagicFeedback("email", "password")

# Tune the Datastore lookup (all optional; shown with their defaults):
client = MagicFeedback(
    "email", "password",
    auth_source="datastore",
    gcp_project_id=None,             # None => inferred from Application Default Credentials
    datastore_database_id="shared",
    token_kind="token-storage",
    token_email="robot@magicfeedback.io",
    token_max_age_min=50,
    datastore_timeout_s=5.0,         # cap the lookup so the fallback stays fast
)

# Original behaviour — always mint a fresh token via Identity Platform:
client = MagicFeedback("email", "password", auth_source="identity")
```

The Datastore lookup is bounded by `datastore_timeout_s` (default 5s): if the
cache is unreachable or the credentials are stale, the client falls back to
Identity Platform within that budget instead of blocking on the Datastore
client's default ~60s retry deadline.

The Datastore path needs the `google-cloud-datastore` package (installed as a
dependency) and Google Application Default Credentials with read access to the
token entity (`gcloud auth application-default login` or
`GOOGLE_APPLICATION_CREDENTIALS`).

Helper methods:

- `client.refresh_token()` — re-resolve the token (same `auth_source`) and
  update the auth header in place across all sub-API clients. Useful for
  long-lived clients whose token has expired.
- `client.auth.get_token_from_datastore(allow_stale=False)` — read the cached
  token directly; returns `None` when missing, stale or unreachable.

## API Reference

### `client.feedbacks`
- `create(feedback)` — creates a new feedback item. Required fields: `name`, `type`, `identity`, `integrationId`, `companyId`, `productId`.
- `get(filter=None)` — lists feedback items.
- `get_id(feedback_id, filter=None)` — retrieves a specific feedback item.
- `update(feedback_id, feedback)` — updates a feedback item.
- `delete(feedback_id)` — deletes a feedback item.
- `upload_attachment(feedback_id, file_path, filename=None, extra_data=None)` — uploads a file and attaches it to a feedback.

### `client.contacts`
- `create(contact)`, `get(filter=None)`, `update(contact_id, contact)`, `delete(contact_id)`

### `client.campaigns`
- `create(campaign)`, `get(filter=None)`
- `create_session(campaign_id, session)`, `get_sessions(campaign_id, filter=None)`, `get_sessions_feedbacks(campaign_id, filter=None)`

### `client.metrics`
- `get(filter=None)`

### `client.products`
- `get(filter=None)`

### `client.companies`
- `get(filter=None)`, `get_id(id, filter=None)`

### `client.integrations_questions`
- `get(integration_id, filter=None)`

### `client.reports`
- `get(filter=None)`, `get_newsletter(filter=None)`, `update(report_id, report)`

### `client.requests`
- `get(filter=None)`, `get_id(request_id, filter=None)`, `update(request_id, request)`
- `publish_done(request_id, company_id, output=None, success=True, status=None, sources=None, sources_key=None, logs=None, quality=None, error=None, project_id=None, topic=None)` — publishes a completion event to the `request-done` Pub/Sub topic. The `request-done` Cloud Function consumes it and PATCHes the request to `DONE` (or `ERROR` when `success=False`). Requires `google-cloud-pubsub` and Google Application Default Credentials with publish rights on the topic. The Pub/Sub project/topic default to PROD (`magicfeedback-prod-agent` / `request-done`); override at construction (`MagicFeedback(..., pubsub_project_id="magicfeedback-dev-agent")`) or per call (`project_id=`, `topic=`).

## Examples

```python
# Create a feedback
client.feedbacks.create({
    "name": "Test Feedback",
    "type": "APP",
    "identity": "MAGICFORM",
    "integrationId": "your-integration-id",
    "companyId": "YOUR_COMPANY",
    "productId": "YOUR_PRODUCT",
    "answers": [
        {"key": "score", "value": "4"},
        {"key": "comment", "value": "Great service!"},
    ],
})

# Get a feedback with its attachments
client.feedbacks.get_id(
    "<feedback_id>",
    filter={"include": [{"relation": "feedbackAttachments"}]}
)

# Upload a file attachment
client.feedbacks.upload_attachment(
    "<feedback_id>",
    file_path="/path/to/file.pdf",
    filename="report.pdf",          # optional, defaults to file name
    extra_data={"source": "crm"}    # optional, any JSON-serialisable dict
)

# Mark a request DONE via the request-done Pub/Sub topic
client.requests.publish_done(
    request_id="<request_id>",
    company_id="<company_id>",
    output={"value": "…final result…"},
    sources=["<feedbackId1>", "<feedbackId2>"],  # optional
    logs="processed 2 items",                     # optional
)

# Mark a request as ERROR
client.requests.publish_done(
    request_id="<request_id>",
    company_id="<company_id>",
    success=False,
    error={"message": "processing failed"},
)
```

## Logging

```python
import logging
client.set_logging(logging.DEBUG)
```

## License

MIT

## Contact

farias@magicfeedback.io
