Metadata-Version: 2.4
Name: nimble-rest-client
Version: 1.0rc4
Summary: Nimble REST OpenAPI
Home-page: 
Author: NimbleWork API Support
Author-email: support@nimblework.com
Keywords: nimblework,nimble,rest,client,api,forms,workspaces,instances
Description-Content-Type: text/markdown
Requires-Dist: urllib3<2.1.0,>=1.25.3
Requires-Dist: python-dateutil
Requires-Dist: pydantic>=2
Requires-Dist: typing-extensions>=4.7.1
Dynamic: author
Dynamic: author-email
Dynamic: description
Dynamic: description-content-type
Dynamic: keywords
Dynamic: requires-dist
Dynamic: summary

# nimble-rest-client

[![PyPI](https://img.shields.io/pypi/v/nimble-rest-client)](https://pypi.org/project/nimble-rest-client/)
[![Python](https://img.shields.io/badge/python-3.8%2B-blue)](https://pypi.org/project/nimble-rest-client/)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue)](https://www.apache.org/licenses/LICENSE-2.0)

Official Python SDK for [NimbleWork](https://www.nimblework.com) REST APIs.

---

## What you can do

- List and get **workspaces** and **forms**
- Full **CRUD** on workitems — create, read, update, delete
- **Flag**, **block**, **vote**, and **link** workitems
- Add **comments** and **attachments**
- Manage **todos** and log **time entries**
- OAuth 2.0 authentication built in

## Documentation

Full guide: [NimbleWork REST API Client](https://www.nimblework.com/knowledge-base/nimble/article/rest-api-client/)

---

## Requirements

- Python 3.8+
- An OAuth 2.0 access token from your NimbleWork account

## Installation

```bash
pip install nimble-rest-client
```

---

## Getting Started

**Step 1 — Get your token**

Go to **Account Settings → API Tokens** in NimbleWork and generate an OAuth 2.0 token.

**Step 2 — Find your IDs**

- **Workspace ID** — visible in the NimbleWork URL
- **Form ID** — from `list_forms(workspace_id)`
- **Instance ID** — from `list_instances(workspace_id)` or `create_instance(...)`

**Step 3 — Initialize**

```python
import nimble_rest_client
from nimble_rest_client.api import workspaces_api, forms_api, instances_api

config = nimble_rest_client.Configuration(
    host='https://api.digite.com',
    access_token='YOUR_OAUTH2_TOKEN',
)

with nimble_rest_client.ApiClient(config) as client:
    ws_api   = workspaces_api.WorkspacesApi(client)
    f_api    = forms_api.FormsApi(client)
    inst_api = instances_api.InstancesApi(client)
```

---

## Examples

### List workspaces

```python
with nimble_rest_client.ApiClient(config) as client:
    api = workspaces_api.WorkspacesApi(client)
    result = api.list_workspaces()
    for ws in result.items:
        print(ws.workspace_id, ws.name)
```

### Get a form by ID

```python
with nimble_rest_client.ApiClient(config) as client:
    api = forms_api.FormsApi(client)
    form = api.get_form_by_id('FORM_ID', workspace_id='WORKSPACE_ID')
    print(form.name)
```

### List workitems

```python
with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    result = api.list_instances('WORKSPACE_ID')
    for item in result.items:
        print(item.instance_id, item.name)
```

### Create a workitem

```python
from nimble_rest_client.models.create_instance_request import CreateInstanceRequest

with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    req = CreateInstanceRequest.from_dict({
        'workspaceId': 'WORKSPACE_ID',
        'formId': 'FORM_ID',
        'Name': 'My new workitem',
    })
    instance = api.create_instance(create_instance_request=req)
    print(instance.instance_id)
```

### Update a workitem (PATCH)

```python
with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    api.update_instance_by_id('INSTANCE_ID', {'Name': 'Updated name'})
```

### Add a comment

```python
from nimble_rest_client.api import comments_api
from nimble_rest_client.models.create_comment_request import CreateCommentRequest

with nimble_rest_client.ApiClient(config) as client:
    api = comments_api.CommentsApi(client)
    api.create_comment(
        instance_id='INSTANCE_ID',
        create_comment_request=CreateCommentRequest(content='This is a comment'),
    )
```

### Flag a workitem

```python
from nimble_rest_client.models.flag_instance_request import FlagInstanceRequest

with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    api.flag_instance(
        instance_id='INSTANCE_ID',
        flag_instance_request=FlagInstanceRequest(comment='Needs attention'),
    )
```

### Block a workitem

```python
from nimble_rest_client.models.block_instance_request import BlockInstanceRequest

with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    api.block_instance(
        instance_id='INSTANCE_ID',
        block_instance_request=BlockInstanceRequest(
            reason='Waiting for design',
            comment='Blocked until design is ready',
        ),
    )
```

### Vote on a workitem

```python
with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    api.vote_instance(instance_id='INSTANCE_ID')    # vote
    api.unvote_instance(instance_id='INSTANCE_ID')  # remove vote
```

### Link two workitems

```python
from nimble_rest_client.models.link_workitem_request import LinkWorkitemRequest
from nimble_rest_client.models.link_workitem_request_to import LinkWorkitemRequestTo

with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    api.link_workitem(
        instance_id='SOURCE_INSTANCE_ID',
        link_workitem_request=LinkWorkitemRequest(
            to=LinkWorkitemRequestTo(
                instance_id='TARGET_INSTANCE_ID',
                form_id='TARGET_FORM_ID',
                work_space_id='TARGET_WORKSPACE_ID',
            ),
            meta_type='DEPENDENCY',
            relation_inverse='fulfills',
        ),
    )
```

### Manage todos

```python
from nimble_rest_client.api import todos_api

with nimble_rest_client.ApiClient(config) as client:
    api = todos_api.TodosApi(client)
    todo = api.create_todo('INSTANCE_ID', {'name': 'Review PR'})
    api.close_todo('INSTANCE_ID', todo.todo_id)
```

### Upload an attachment

```python
from nimble_rest_client.api import attachments_api

with nimble_rest_client.ApiClient(config) as client:
    api = attachments_api.AttachmentsApi(client)
    api.create_attachment('INSTANCE_ID', file='/path/to/file.pdf')
```

### Log time on a workitem

```python
from nimble_rest_client.api import time_entries_api

with nimble_rest_client.ApiClient(config) as client:
    api = time_entries_api.TimeEntriesApi(client)
    api.create_time_entry('INSTANCE_ID', {
        'todoId': 'TODO_ID',
        'date': '2024-06-01',
        'actualHours': 2,
        'remainingHours': 3,
    })
```

---

## Error Handling

```python
from nimble_rest_client.exceptions import ApiException

with nimble_rest_client.ApiClient(config) as client:
    api = instances_api.InstancesApi(client)
    try:
        instance = api.get_instance_by_id('INSTANCE_ID')
        print(instance)
    except ApiException as e:
        print(f"API error {e.status}: {e.reason}")
    except Exception as e:
        print(f"Network error: {e}")
```

---

## Available APIs

| Class | Description |
|---|---|
| `WorkspacesApi` | List and get workspaces |
| `FormsApi` | List and get forms |
| `InstancesApi` | Full CRUD on workitems, plus flag/block/vote/link |
| `CommentsApi` | Add and list comments |
| `AttachmentsApi` | Upload and list attachments |
| `TodosApi` | Create, update, close, and delete todos |
| `TimeEntriesApi` | Log time entries |

---

## Authentication

All endpoints require an OAuth 2.0 bearer token.

```python
config = nimble_rest_client.Configuration(
    host='https://api.digite.com',
    access_token='YOUR_TOKEN_HERE',
)
```

---

## Support

For questions or issues, contact **NimbleWork API Support** at itops@digite.com.
