# Units service (gRPC)

The Units Service serves as a comprehensive catalog of the units of measurement supported by Nominal. Units, by default, follow the UCUM convention for representation.

## Endpoints

### Get all units

gRPC `/nominal.units.v1.UnitsService/GetAllUnits`

Returns all known units, grouped by the physical property they measure.

Request: `GetAllUnitsRequest`

A message with no fields.

Response: `GetAllUnitsResponse`

`units_by_property` map of string to [`GetUnitsResponseUnitsByPropertyWrapper`](https://dev.nominal.io/api/grpc/units-service.md#getunitsresponseunitsbypropertywrapper)
:   ​

    Fields of `GetUnitsResponseUnitsByPropertyWrapper`

    `value` array of [`Unit`](https://dev.nominal.io/api/grpc/units-service.md#unit)
    :   ​

        Fields of `Unit`

        `name` string
        :   ​

        `symbol` string
        :   ​

        `property` string
        :   Empty if no property is available. If two units measure different properties, it is not possible to convert between them.

        `dimension` [`UnitDimension`](https://dev.nominal.io/api/grpc/units-service.md#unitdimension)
        :   The physical dimensions in terms of the base units of the system. It is only possible to convert units if they have the same dimension. Empty if the unit is a base unit.

            Fields of `UnitDimension`

            `base_dimensions` map of string to integer
            :   ​

        `system` string
        :   ​

Request

**Python**

```python
import grpc
from nominal.protos.units.v1 import units_pb2, units_pb2_grpc

channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
units_service = units_pb2_grpc.UnitsServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]

request = units_pb2.GetAllUnitsRequest()
response = units_service.GetAllUnits(request, metadata=auth)
print(response)
```

**Go**

```go
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"

	unitsv1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/units/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
)

func main() {
	conn, err := grpc.NewClient("api.gov.nominal.io:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	unitsService := unitsv1.NewUnitsServiceClient(conn)
	ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")

	request := &unitsv1.GetAllUnitsRequest{}
	response, err := unitsService.GetAllUnits(ctx, request)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response)
}
```

Response

```json
{
  "units_by_property": {
    "<key>": {
      "value": [
        {
          "name": "<name>",
          "symbol": "<symbol>",
          "property": "<property>",
          "dimension": {
            "base_dimensions": {
              "<key>": 1
            }
          },
          "system": "<system>"
        }
      ]
    }
  }
}
```

### Get batch units

gRPC `/nominal.units.v1.UnitsService/GetBatchUnits`

Returns information for the unit symbols if available. If the provided symbol cannot be parsed, it will be omitted from the map.

Request: `GetBatchUnitsRequest`

`units` array of string
:   ​

Response: `GetBatchUnitsResponse`

`responses` map of string to [`Unit`](https://dev.nominal.io/api/grpc/units-service.md#unit)
:   ​

    Fields of `Unit`

    `name` string
    :   ​

    `symbol` string
    :   ​

    `property` string
    :   Empty if no property is available. If two units measure different properties, it is not possible to convert between them.

    `dimension` [`UnitDimension`](https://dev.nominal.io/api/grpc/units-service.md#unitdimension)
    :   The physical dimensions in terms of the base units of the system. It is only possible to convert units if they have the same dimension. Empty if the unit is a base unit.

        Fields of `UnitDimension`

        `base_dimensions` map of string to integer
        :   ​

    `system` string
    :   ​

Request

**Python**

```python
import grpc
from nominal.protos.units.v1 import units_pb2, units_pb2_grpc

channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
units_service = units_pb2_grpc.UnitsServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]

request = units_pb2.GetBatchUnitsRequest(units=["<units>"])
response = units_service.GetBatchUnits(request, metadata=auth)
print(response)
```

**Go**

```go
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"

	unitsv1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/units/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
)

func main() {
	conn, err := grpc.NewClient("api.gov.nominal.io:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	unitsService := unitsv1.NewUnitsServiceClient(conn)
	ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")

	request := &unitsv1.GetBatchUnitsRequest{
		Units: []string{
			"<units>",
		},
	}
	response, err := unitsService.GetBatchUnits(ctx, request)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response)
}
```

Response

```json
{
  "responses": {
    "<key>": {
      "name": "<name>",
      "symbol": "<symbol>",
      "property": "<property>",
      "dimension": {
        "base_dimensions": {
          "<key>": 1
        }
      },
      "system": "<system>"
    }
  }
}
```

### Get commensurable units

gRPC `/nominal.units.v1.UnitsService/GetCommensurableUnits`

Returns the set of cataloged units that can be converted to and from the given unit. No commensurable units does not imply the unit is invalid. Use /get-unit to check for validity.

Request: `GetCommensurableUnitsRequest`

`unit` string
:   ​

Response: `GetCommensurableUnitsResponse`

`units` array of [`Unit`](https://dev.nominal.io/api/grpc/units-service.md#unit)
:   ​

    Fields of `Unit`

    `name` string
    :   ​

    `symbol` string
    :   ​

    `property` string
    :   Empty if no property is available. If two units measure different properties, it is not possible to convert between them.

    `dimension` [`UnitDimension`](https://dev.nominal.io/api/grpc/units-service.md#unitdimension)
    :   The physical dimensions in terms of the base units of the system. It is only possible to convert units if they have the same dimension. Empty if the unit is a base unit.

        Fields of `UnitDimension`

        `base_dimensions` map of string to integer
        :   ​

    `system` string
    :   ​

Request

**Python**

```python
import grpc
from nominal.protos.units.v1 import units_pb2, units_pb2_grpc

channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
units_service = units_pb2_grpc.UnitsServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]

request = units_pb2.GetCommensurableUnitsRequest(unit="<unit>")
response = units_service.GetCommensurableUnits(request, metadata=auth)
print(response)
```

**Go**

```go
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"

	unitsv1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/units/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
)

func main() {
	conn, err := grpc.NewClient("api.gov.nominal.io:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	unitsService := unitsv1.NewUnitsServiceClient(conn)
	ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")

	request := &unitsv1.GetCommensurableUnitsRequest{
		Unit: "<unit>",
	}
	response, err := unitsService.GetCommensurableUnits(ctx, request)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response)
}
```

Response

```json
{
  "units": [
    {
      "name": "<name>",
      "symbol": "<symbol>",
      "property": "<property>",
      "dimension": {
        "base_dimensions": {
          "<key>": 1
        }
      },
      "system": "<system>"
    }
  ]
}
```

### Get unit

gRPC `/nominal.units.v1.UnitsService/GetUnit`

Returns information for a unit symbol if available. Returns as empty if the provided symbol cannot be parsed.

Request: `GetUnitRequest`

`unit` string
:   ​

Response: `GetUnitResponse`

`unit` [`Unit`](https://dev.nominal.io/api/grpc/units-service.md#unit)
:   ​

    Fields of `Unit`

    `name` string
    :   ​

    `symbol` string
    :   ​

    `property` string
    :   Empty if no property is available. If two units measure different properties, it is not possible to convert between them.

    `dimension` [`UnitDimension`](https://dev.nominal.io/api/grpc/units-service.md#unitdimension)
    :   The physical dimensions in terms of the base units of the system. It is only possible to convert units if they have the same dimension. Empty if the unit is a base unit.

        Fields of `UnitDimension`

        `base_dimensions` map of string to integer
        :   ​

    `system` string
    :   ​

Request

**Python**

```python
import grpc
from nominal.protos.units.v1 import units_pb2, units_pb2_grpc

channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
units_service = units_pb2_grpc.UnitsServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]

request = units_pb2.GetUnitRequest(unit="<unit>")
response = units_service.GetUnit(request, metadata=auth)
print(response)
```

**Go**

```go
package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"

	unitsv1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/units/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
)

func main() {
	conn, err := grpc.NewClient("api.gov.nominal.io:443",
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	unitsService := unitsv1.NewUnitsServiceClient(conn)
	ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")

	request := &unitsv1.GetUnitRequest{
		Unit: "<unit>",
	}
	response, err := unitsService.GetUnit(ctx, request)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response)
}
```

Response

```json
{
  "unit": {
    "name": "<name>",
    "symbol": "<symbol>",
    "property": "<property>",
    "dimension": {
      "base_dimensions": {
        "<key>": 1
      }
    },
    "system": "<system>"
  }
}
```

## Errors

[Errors](https://dev.nominal.io/api/grpc.md#errors) shows how these errors are sent.

| Code | Reason | Message |
| --- | --- | --- |
| `INVALID_ARGUMENT` | `SCOUT_ERROR_CANNOT_DESERIALIZE_SEARCH_TOKEN` | CannotDeserializeSearchToken |
| `INVALID_ARGUMENT` | `SCOUT_ERROR_INVALID_RANGE` | The start time of the provided Range is greater than its end time. |
| `INVALID_ARGUMENT` | `SCOUT_ERROR_REQUESTED_PAGE_SIZE_TOO_LARGE` | RequestedPageSizeTooLarge |

## Types

### GetUnitsResponseUnitsByPropertyWrapper

`value` array of [`Unit`](https://dev.nominal.io/api/grpc/units-service.md#unit)
:   ​

### Unit

`name` string
:   ​

`symbol` string
:   ​

`property` string
:   Empty if no property is available. If two units measure different properties, it is not possible to convert between them.

`dimension` [`UnitDimension`](https://dev.nominal.io/api/grpc/units-service.md#unitdimension)
:   The physical dimensions in terms of the base units of the system. It is only possible to convert units if they have the same dimension. Empty if the unit is a base unit.

`system` string
:   ​

### UnitDimension

The fundamental base dimensions and their exponents, whose product compose a unit.

`base_dimensions` map of string to integer
:   ​

Page design based on [Scalar](https://scalar.com), MIT License.
