# Declare a resource binding

> Declare an Orchestrator or Integration Service resource in bindings.json, verify it resolves during a local run, and make it remappable across tenants.

`bindings.json` is maintained by hand: `uipath init` creates the file with the required structure when it is absent, and leaves an existing file untouched. Declare a binding for every platform resource your function reaches, so the resource can be remapped when the package runs in another tenant. For the resolution mechanism behind this, see [Resource bindings](resource-bindings.md).

## Prerequisites

- A Python function project created with `uipath new`.
- An authenticated session, established with `uipath auth`.
- The resource already exists in the tenant you develop against.
- The UiPath CLI (`uip`) is installed, for the connection lookup in step 1.

## Declare a connection binding

1. Retrieve the connection id from Integration Service:

   ```bash
   uip is connections list uipath-microsoft-outlook365
   ```

2. Open `bindings.json` at the project root.

3. Add an entry to the `resources` array, using the connection id for both `key` and `ConnectionId.defaultValue`:

   ```json
   {
     "resource": "connection",
     "key": "<connection-id>",
     "value": {
       "ConnectionId": {
         "defaultValue": "<connection-id>",
         "isExpression": false,
         "displayName": "Microsoft Outlook 365 Connection"
       },
       "Connector": {
         "defaultValue": "uipath-microsoft-outlook365",
         "isExpression": false,
         "displayName": "Connector"
       }
     },
     "metadata": {
       "Connector": "uipath-microsoft-outlook365",
       "UseConnectionService": "True",
       "BindingsVersion": "2.2"
     }
   }
   ```

4. Declare the same id as a module-level constant in your function, and pass it to the SDK call:

   ```python
   OUTLOOK_CONNECTION_KEY = "<connection-id>"

   conn = sdk.connections.retrieve(OUTLOOK_CONNECTION_KEY)
   ```

5. Run the function locally:

   ```bash
   uipath run main -f input.json
   ```

### Result

The run log contains one line per declared binding:

```
No resource overwrite matched for connection key='connection.<connection-id>' on retrieve
```

This line confirms the override lookup ran and fell back to the design-time id, which is the expected outcome locally because no tenant mapping exists. If the line names a different id than the one in `bindings.json`, the code constant and the binding disagree.

:::note
Declaring bindings for other resource types follows the same pattern with a different `value` shape. Assets, buckets, queues, processes, apps, and indexes use `name` and `folderPath` instead of `ConnectionId`, and their `key` joins the two with a dot.
:::

## Make the binding remappable across tenants

1. Register the function project in a solution:

   ```bash
   uip solution project add ./my-solution/my-function
   ```

2. Sync the solution's resource list from the project's declared bindings:

   ```bash
   uip solution resource refresh
   ```

3. Review the resulting resource list:

   ```bash
   uip solution resource list --source local
   ```

### Result

Every declared binding appears in the solution's local resource list. Deployment maps each entry to a resource in the target tenant, so the same package runs against that tenant's own connection. For packaging and publishing the solution, see [`uip solution pack`](https://docs.uipath.com/uipath-cli/standalone/latest/user-guide/uip-solution-pack).

:::warning
A binding that is not mapped in the target tenant does not fail the job. The call falls back to the design-time identifier, so verify that every binding appears in the target tenant's resource mapping before promoting a solution.
:::

## Next steps

- [Call an Integration Service activity](calling-integration-service-activities.md) — use a declared connection to reach a connector operation.
- [Packaging and publishing](packaging-and-publishing.md) — deploy the function to Orchestrator.
