# Hash Data API

> Hash a value with the hash data system API of API Maker - HMAC SHA-256 with the nonce or secret of your secret, the same hash the hashing conversion of a schema stores, so you can look a hashed column up.

Source: https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-hash-data-api.html

Answers the SHA-256 hash of the body, computed with the `nonce` (or, without one, the `secret`) of the default secret. A string is hashed as it is, exactly like the `hashing` conversion of a [schema](https://docs.apimaker.dev/v4/docs/schema/schema.html) hashes a field, so the hash of a password or a tax id given here equals the one stored in the table and can be used to find the row.

| | |
|---|---|
| Method | POST |
| URL | `/api/system-api/admin/hash-data` : `admin` is the user path of your account |
| Body | the value to hash : a string, or any JSON |
| Answer | `data` : the hash, a hex string |
| From code | [`g.sys.system.hash`](https://docs.apimaker.dev/v4/docs/apis-all/system-apis/system-generated-hash-data-api.html#look-up-a-hashed-column) |

## The call

**Body : a string**

```json
"Joseph"
```

**Body : an object (hashed as its JSON text)**

```json
{ "name": "Joseph" }
```

**Answer**

```json
{ "success": true, "statusCode": 200, "data": "be2a6a457cc36a48e4e231411d8d6498213f7ffb6d1e03066dd7fbaa6ec9402e" }
```

- The algorithm is `hashingAlgorithm` of the secret : `SHA256` is the one supported.
- The same value always gives the same hash for the same secret, which is the point : hash a value on the way in and compare hashes on the way out.

## Look up a hashed column

**TypeScript**

**Find the customer whose tax id (hashed in the table) is known**

```typescript
const taxId = g.req.body.taxId;
const digest = await g.sys.system.hash(taxId);
const suppliers = await g.sys.db.query({ instance: 'mongodb', database: 'shop', collection: 'suppliers', find: { tax_id_hash: digest } });
```

**Python**

**Find the customer whose tax id (hashed in the table) is known**

```python
tax_id = g.req.body.taxId
digest = await g.sys.system.hash(tax_id)
suppliers = await g.sys.db.query('mongodb', 'shop', 'suppliers', find={'tax_id_hash': digest})
```

**PHP**

**Find the customer whose tax id (hashed in the table) is known**

```php
$taxId = $g->req->body->taxId;
$digest = $g->sys->system->hash($taxId);
$suppliers = $g->sys->db->query('mongodb', 'shop', 'suppliers', find: ['tax_id_hash' => $digest]);
```

**C#**

**Find the customer whose tax id (hashed in the table) is known**

```csharp
var taxId = g.Req.Body.GetString("taxId");
var digest = await g.Sys.System.Hash(taxId);
var suppliers = await g.Sys.Db.Query(new Query("mongodb", "shop", "suppliers") { Find = new JsonObject { ["tax_id_hash"] = digest } });
```

**Go**

**Find the customer whose tax id (hashed in the table) is known**

```go
taxId := g.Req.Body().String("taxId")
digest, err := g.Sys.System.Hash(taxId)
if err != nil {
	return nil, err
}
suppliers, err := g.Sys.Db.Query(am.Query{Instance: "mongodb", Database: "shop", Collection: "suppliers", Find: am.M{"tax_id_hash": digest}})
if err != nil {
	return nil, err
}
```

**Rust**

**Find the customer whose tax id (hashed in the table) is known**

```rust
let tax_id = g.req.body()["taxId"].clone();
let digest = g.sys.system.hash(tax_id)?;
let suppliers = g.sys.db.query(Query::new("mongodb", "shop", "suppliers").find(json!({ "tax_id_hash": digest })))?;
```

**Java**

**Find the customer whose tax id (hashed in the table) is known**

```java
String taxId = g.req.getBody().getString("taxId");
String digest = g.sys.system.hash(taxId);
List<JsonObject> suppliers = g.sys.db.query(new Query("mongodb", "shop", "suppliers").find(Map.of("tax_id_hash", digest)));
```

**Kotlin**

**Find the customer whose tax id (hashed in the table) is known**

```kotlin
val taxId = g.req.body.getString("taxId")
val digest = g.sys.system.hash(taxId)
val suppliers = g.sys.db.query(Query("mongodb", "shop", "suppliers").find(mapOf("tax_id_hash" to digest)))
```

- Keep an encrypted copy of the value in another field when you also need to read it back : encryption is reversible, hashing is not.

## Access and settings

- Over HTTP, a system API answers once its [settings](https://docs.apimaker.dev/v4/docs/settings/systemApiSettings.html) give it `apiAccessType: TOKEN_ACCESS` (the token of an API user whose [group](https://docs.apimaker.dev/v4/docs/apis-security/api-group-permission.html) grants this system API, in `x-am-authorization`) or `IS_PUBLIC`. Without settings it is `NO_ACCESS` : your code calls it through `g.sys`, the admin panel tests it, and an HTTP call is refused.
- The settings can also cache the answer or require person tokens (`authProviders`) ; [pre and post hooks](https://docs.apimaker.dev/v4/docs/apis-all/hooks/preHook-api.html) run around it like around any API.
- The [request headers](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html) apply : `x-am-response-case`, `x-am-content-type-response`, `x-am-internationalization`, `x-am-tenant-username`…

## Errors

| Code | When |
|---|---|
| `400` | The body is wrong : the message names the missing or invalid key. |
| `401` | No valid API user token, or the API is `NO_ACCESS` : `You are not authorized to access this API.` |
| `403` | No group grants this system API. |

## Related

- [All APIs at a glance](https://docs.apimaker.dev/v4/docs/apis-all/overview.html) · [Response format](https://docs.apimaker.dev/v4/docs/apis-all/response-format.html) · [System API settings](https://docs.apimaker.dev/v4/docs/settings/systemApiSettings.html) · [System APIs from code](https://docs.apimaker.dev/v4/examples/sys/system/system.html)
