> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.mercoa.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mercoa.com/_mcp/server.

# JWT Authentication

> Learn how Mercoa uses JWT tokens for frontend authentication, including token creation, revocation, and session management.

Mercoa uses JSON Web Tokens (JWTs) for frontend authentication. JWTs provide a secure and efficient way to authenticate users and control access to the Mercoa platform.

## JWT Creation

JWTs can be created at multiple levels within your organization:

### Entity Level

### Request

POST [https://api.mercoa.com/entity/\{entityId}/token](https://api.mercoa.com/entity/\{entityId}/token)

**`Default`**

```curl Default
curl -X POST https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "expiresIn": "1h"
}'
```

**`Default`**

```python Default
import requests

url = "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

payload = { "expiresIn": "1h" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Default`**

```typescript Default
import { MercoaClient } from "@mercoa/javascript";

const client = new MercoaClient({ token: "YOUR_TOKEN" });
await client.entity.getToken("ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced", {
    expiresIn: "1h"
});

```

**`Default`**

```go Default
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

	payload := strings.NewReader("{\n  \"expiresIn\": \"1h\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Default`**

```ruby Default
require 'uri'
require 'net/http'

url = URI("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"expiresIn\": \"1h\"\n}"

response = http.request(request)
puts response.read_body
```

**`Default`**

```java Default
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"expiresIn\": \"1h\"\n}")
  .asString();
```

**`Default`**

```php Default
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token', [
  'body' => '{
  "expiresIn": "1h"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Default`**

```csharp Default
using RestSharp;

var client = new RestClient("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"expiresIn\": \"1h\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Default`**

```swift Default
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["expiresIn": "1h"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Entity User Level

### Request

POST [https://api.mercoa.com/entity/\{entityId}/user/\{userId}/token](https://api.mercoa.com/entity/\{entityId}/user/\{userId}/token)

**`Default`**

```curl Default
curl -X POST https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "expiresIn": "1h"
}'
```

**`Default`**

```python Default
import requests

url = "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

payload = { "expiresIn": "1h" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Default`**

```typescript Default
import { MercoaClient } from "@mercoa/javascript";

const client = new MercoaClient({ token: "YOUR_TOKEN" });
await client.entity.user.getToken("ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced", "user_a0f6ea94-0761-4a5e-a416-3c453cb7eced", {
    expiresIn: "1h"
});

```

**`Default`**

```go Default
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

	payload := strings.NewReader("{\n  \"expiresIn\": \"1h\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Default`**

```ruby Default
require 'uri'
require 'net/http'

url = URI("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"expiresIn\": \"1h\"\n}"

response = http.request(request)
puts response.read_body
```

**`Default`**

```java Default
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"expiresIn\": \"1h\"\n}")
  .asString();
```

**`Default`**

```php Default
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token', [
  'body' => '{
  "expiresIn": "1h"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Default`**

```csharp Default
using RestSharp;

var client = new RestClient("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"expiresIn\": \"1h\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Default`**

```swift Default
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["expiresIn": "1h"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/user_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Entity Group Level

### Request

POST [https://api.mercoa.com/entityGroup/\{entityGroupId}/token](https://api.mercoa.com/entityGroup/\{entityGroupId}/token)

**`Default`**

```curl Default
curl -X POST https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "expiresIn": "1h"
}'
```

**`Default`**

```python Default
import requests

url = "https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

payload = { "expiresIn": "1h" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Default`**

```typescript Default
import { MercoaClient } from "@mercoa/javascript";

const client = new MercoaClient({ token: "YOUR_TOKEN" });
await client.entityGroup.getToken("entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced", {
    expiresIn: "1h"
});

```

**`Default`**

```go Default
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

	payload := strings.NewReader("{\n  \"expiresIn\": \"1h\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Default`**

```ruby Default
require 'uri'
require 'net/http'

url = URI("https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"expiresIn\": \"1h\"\n}"

response = http.request(request)
puts response.read_body
```

**`Default`**

```java Default
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"expiresIn\": \"1h\"\n}")
  .asString();
```

**`Default`**

```php Default
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token', [
  'body' => '{
  "expiresIn": "1h"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Default`**

```csharp Default
using RestSharp;

var client = new RestClient("https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"expiresIn\": \"1h\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Default`**

```swift Default
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["expiresIn": "1h"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Entity Group User Level

### Request

POST [https://api.mercoa.com/entityGroup/\{entityGroupId}/user/\{foreignId}/token](https://api.mercoa.com/entityGroup/\{entityGroupId}/user/\{foreignId}/token)

**`Default`**

```curl Default
curl -X POST https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "expiresIn": "1h"
}'
```

**`Default`**

```python Default
import requests

url = "https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token"

payload = { "expiresIn": "1h" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Default`**

```typescript Default
import { MercoaClient } from "@mercoa/javascript";

const client = new MercoaClient({ token: "YOUR_TOKEN" });
await client.entityGroup.user.getToken("entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced", "MY-DB-ID-12345", {
    expiresIn: "1h"
});

```

**`Default`**

```go Default
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token"

	payload := strings.NewReader("{\n  \"expiresIn\": \"1h\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Default`**

```ruby Default
require 'uri'
require 'net/http'

url = URI("https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"expiresIn\": \"1h\"\n}"

response = http.request(request)
puts response.read_body
```

**`Default`**

```java Default
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"expiresIn\": \"1h\"\n}")
  .asString();
```

**`Default`**

```php Default
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token', [
  'body' => '{
  "expiresIn": "1h"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Default`**

```csharp Default
using RestSharp;

var client = new RestClient("https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"expiresIn\": \"1h\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Default`**

```swift Default
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["expiresIn": "1h"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/entityGroup/entg_a0f6ea94-0761-4a5e-a416-3c453cb7eced/user/MY-DB-ID-12345/token")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

## Token Revocation

All JWTs can be revoked at the organization level using the `invalidateTokens` endpoint:

### Request

POST [https://api.mercoa.com/organization/invalidateTokens](https://api.mercoa.com/organization/invalidateTokens)

**`All Sessions`**

```curl All Sessions
curl -X POST https://api.mercoa.com/organization/invalidateTokens \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "sessionId": null
}'
```

**`All Sessions`**

```python All Sessions
import requests

url = "https://api.mercoa.com/organization/invalidateTokens"

payload = { "sessionId": None }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`All Sessions`**

```typescript All Sessions
import { MercoaClient } from "@mercoa/javascript";

const client = new MercoaClient({ token: "YOUR_TOKEN" });
await client.organization.invalidateTokens();

```

**`All Sessions`**

```go All Sessions
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.mercoa.com/organization/invalidateTokens"

	payload := strings.NewReader("{\n  \"sessionId\": null\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`All Sessions`**

```ruby All Sessions
require 'uri'
require 'net/http'

url = URI("https://api.mercoa.com/organization/invalidateTokens")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"sessionId\": null\n}"

response = http.request(request)
puts response.read_body
```

**`All Sessions`**

```java All Sessions
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.mercoa.com/organization/invalidateTokens")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"sessionId\": null\n}")
  .asString();
```

**`All Sessions`**

```php All Sessions
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.mercoa.com/organization/invalidateTokens', [
  'body' => '{
  "sessionId": null
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`All Sessions`**

```csharp All Sessions
using RestSharp;

var client = new RestClient("https://api.mercoa.com/organization/invalidateTokens");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"sessionId\": null\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`All Sessions`**

```swift All Sessions
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["sessionId": ] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/organization/invalidateTokens")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

## Session Management

JWTs can be created with a session ID, which is controlled by the platform. This allows for more granular control over token lifecycle:

### Request

POST [https://api.mercoa.com/entity/\{entityId}/token](https://api.mercoa.com/entity/\{entityId}/token)

**`SessionID`**

```curl SessionID
curl -X POST https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "expiresIn": "1h",
  "sessionId": "session_123"
}'
```

**`SessionID`**

```python SessionID
import requests

url = "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

payload = {
    "expiresIn": "1h",
    "sessionId": "session_123"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`SessionID`**

```typescript SessionID
import { MercoaClient } from "@mercoa/javascript";

const client = new MercoaClient({ token: "YOUR_TOKEN" });
await client.entity.getToken("ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced", {
    expiresIn: "1h",
    sessionId: "session_123"
});

```

**`SessionID`**

```go SessionID
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token"

	payload := strings.NewReader("{\n  \"expiresIn\": \"1h\",\n  \"sessionId\": \"session_123\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`SessionID`**

```ruby SessionID
require 'uri'
require 'net/http'

url = URI("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"expiresIn\": \"1h\",\n  \"sessionId\": \"session_123\"\n}"

response = http.request(request)
puts response.read_body
```

**`SessionID`**

```java SessionID
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"expiresIn\": \"1h\",\n  \"sessionId\": \"session_123\"\n}")
  .asString();
```

**`SessionID`**

```php SessionID
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token', [
  'body' => '{
  "expiresIn": "1h",
  "sessionId": "session_123"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`SessionID`**

```csharp SessionID
using RestSharp;

var client = new RestClient("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"expiresIn\": \"1h\",\n  \"sessionId\": \"session_123\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`SessionID`**

```swift SessionID
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "expiresIn": "1h",
  "sessionId": "session_123"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/token")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

Sessions will automatically be invalidated if a new token for that session is not created within 24 hours. This time limit is subject to change.

To revoke tokens for a specific sessions:

### Request

POST [https://api.mercoa.com/organization/invalidateTokens](https://api.mercoa.com/organization/invalidateTokens)

**`Sessions`**

```curl Sessions
curl -X POST https://api.mercoa.com/organization/invalidateTokens \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "sessionId": [
    "session_123",
    "session_456"
  ]
}'
```

**`Sessions`**

```python Sessions
import requests

url = "https://api.mercoa.com/organization/invalidateTokens"

payload = { "sessionId": ["session_123", "session_456"] }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Sessions`**

```typescript Sessions
import { MercoaClient } from "@mercoa/javascript";

const client = new MercoaClient({ token: "YOUR_TOKEN" });
await client.organization.invalidateTokens({
    sessionId: ["session_123", "session_456"]
});

```

**`Sessions`**

```go Sessions
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.mercoa.com/organization/invalidateTokens"

	payload := strings.NewReader("{\n  \"sessionId\": [\n    \"session_123\",\n    \"session_456\"\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Sessions`**

```ruby Sessions
require 'uri'
require 'net/http'

url = URI("https://api.mercoa.com/organization/invalidateTokens")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"sessionId\": [\n    \"session_123\",\n    \"session_456\"\n  ]\n}"

response = http.request(request)
puts response.read_body
```

**`Sessions`**

```java Sessions
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.mercoa.com/organization/invalidateTokens")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"sessionId\": [\n    \"session_123\",\n    \"session_456\"\n  ]\n}")
  .asString();
```

**`Sessions`**

```php Sessions
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.mercoa.com/organization/invalidateTokens', [
  'body' => '{
  "sessionId": [
    "session_123",
    "session_456"
  ]
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Sessions`**

```csharp Sessions
using RestSharp;

var client = new RestClient("https://api.mercoa.com/organization/invalidateTokens");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"sessionId\": [\n    \"session_123\",\n    \"session_456\"\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Sessions`**

```swift Sessions
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["sessionId": ["session_123", "session_456"]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/organization/invalidateTokens")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

## Role-Based Access Control

JWTs work in conjunction with Mercoa's Role-Based Access Control (RBAC) system. The roles and permissions assigned to a user are encoded in the JWT, ensuring that users can only access the resources and perform the actions they are authorized for.

For more information about roles and permissions, see our [RBAC documentation](/common-concepts/rbac).

## Best Practices

1. **Token Expiration**: Set appropriate expiration times for your JWTs based on your security requirements. Shorter expiration times are generally more secure.

2. **Session Management**: Use session IDs when you need to track and manage user sessions, especially for features like "logout everywhere" or session invalidation.

3. **Token Storage**: Store JWTs securely in your frontend application or not at all. Consider using secure HTTP-only cookies or secure local storage mechanisms.

4. **Token Refresh**: Implement a token refresh mechanism for long-lived sessions to maintain security while providing a good user experience.