> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fga.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# How To Update Relationship Tuples

> Introduction to adding and deleting relationship tuples

This is an introduction to adding and deleting *[relationship tuples](https://docs.fga.dev/fga-concepts.md#what-is-a-relationship-tuple)*.

## Before you start

**Node.js**

1. You have [obtained FGA API credentials](https://docs.fga.dev/integration/getting-your-api-keys.md) and set `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID`, and `FGA_CLIENT_SECRET`.
2. You have [installed the SDK](https://docs.fga.dev/integration/install-sdk.md).
3. You have [configured the *authorization model*](https://docs.fga.dev/modeling.md).
4. You have loaded `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID` and `FGA_CLIENT_SECRET` as environment variables.

**Go**

1. You have [obtained FGA API credentials](https://docs.fga.dev/integration/getting-your-api-keys.md) and set `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID`, and `FGA_CLIENT_SECRET`.
2. You have [installed the SDK](https://docs.fga.dev/integration/install-sdk.md).
3. You have [configured the *authorization model*](https://docs.fga.dev/modeling.md).
4. You have loaded `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID` and `FGA_CLIENT_SECRET` as environment variables.

**.NET**

1. You have [obtained FGA API credentials](https://docs.fga.dev/integration/getting-your-api-keys.md) and set `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID`, and `FGA_CLIENT_SECRET`.
2. You have [installed the SDK](https://docs.fga.dev/integration/install-sdk.md).
3. You have [configured the *authorization model*](https://docs.fga.dev/modeling.md).
4. You have loaded `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID` and `FGA_CLIENT_SECRET` as environment variables.

**Python**

1. You have [obtained FGA API credentials](https://docs.fga.dev/integration/getting-your-api-keys.md) and set `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID`, and `FGA_CLIENT_SECRET`.
2. You have [installed the SDK](https://docs.fga.dev/integration/install-sdk.md).
3. You have [configured the *authorization model*](https://docs.fga.dev/modeling.md).
4. You have loaded `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID` and `FGA_CLIENT_SECRET` as environment variables.

**Java**

1. You have [obtained FGA API credentials](https://docs.fga.dev/integration/getting-your-api-keys.md) and set `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID`, and `FGA_CLIENT_SECRET`.
2. You have [installed the SDK](https://docs.fga.dev/integration/install-sdk.md).
3. You have [configured the *authorization model*](https://docs.fga.dev/modeling.md).
4. You have loaded `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID` and `FGA_CLIENT_SECRET` as environment variables.

**CLI**

1. You have [obtained FGA API credentials](https://docs.fga.dev/integration/getting-your-api-keys.md) and set `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID`, and `FGA_CLIENT_SECRET`.
2. You have [installed the CLI](https://docs.fga.dev/integration/install-sdk.md).
3. You have [configured the *authorization model*](https://docs.fga.dev/modeling.md).
4. You have loaded `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID` and `FGA_CLIENT_SECRET` as environment variables.

**curl**

1. You have [obtained FGA API credentials](https://docs.fga.dev/integration/getting-your-api-keys.md) and set `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID`, and `FGA_CLIENT_SECRET`.
2. You have [configured the *authorization model*](https://docs.fga.dev/modeling.md).
3. You have loaded `FGA_API_URL`, `FGA_STORE_ID`, `FGA_API_TOKEN_ISSUER`, `FGA_API_AUDIENCE`, `FGA_CLIENT_ID` and `FGA_CLIENT_SECRET` as environment variables.

## Step by step

Assume that you want to add user `user:anne` to have relationship `reader` with object `document:Z`

```json theme={null}
{
  user: 'user:anne',
  relation: 'reader',
  object: 'document:Z'
}
```

### 01. Configure the Auth0 FGA API client

Before calling the write API, you will need to configure the API client.

**Node.js**

```javascript theme={null}
const { CredentialsMethod, OpenFgaClient, ConsistencyPreference, ClientWriteRequestOnDuplicateWrites, ClientWriteRequestOnMissingDeletes } = require('@openfga/sdk');

const fgaClient = new OpenFgaClient({
  apiUrl: process.env.FGA_API_URL, // https://api.us1.fga.dev, or your store's eu1/au1 region
  storeId: process.env.FGA_STORE_ID,
  authorizationModelId: process.env.FGA_MODEL_ID,
  credentials: {
    method: CredentialsMethod.ClientCredentials,
    config: {
      apiTokenIssuer: process.env.FGA_API_TOKEN_ISSUER, // auth.fga.dev
      apiAudience: process.env.FGA_API_AUDIENCE, // URL for your store's region
      clientId: process.env.FGA_CLIENT_ID,
      clientSecret: process.env.FGA_CLIENT_SECRET,
    },
  },
});
```

**Go**

```go theme={null}
package main

import (
    "os"
    . "github.com/openfga/go-sdk/client"
    "github.com/openfga/go-sdk/credentials"
)

// Configure FGA_API_URL and FGA_API_AUDIENCE for your store's us1/eu1/au1 region.
// Set FGA_STORE_ID, FGA_MODEL_ID, FGA_API_TOKEN_ISSUER, FGA_CLIENT_ID, and FGA_CLIENT_SECRET.
func main() {
    fgaClient, err := NewSdkClient(&ClientConfiguration{
        ApiUrl: os.Getenv("FGA_API_URL"),
        StoreId: os.Getenv("FGA_STORE_ID"),
        AuthorizationModelId: os.Getenv("FGA_MODEL_ID"),
        Credentials: &credentials.Credentials{
            Method: credentials.CredentialsMethodClientCredentials,
            Config: &credentials.Config{
                ClientCredentialsApiTokenIssuer: os.Getenv("FGA_API_TOKEN_ISSUER"),
                ClientCredentialsApiAudience: os.Getenv("FGA_API_AUDIENCE"),
                ClientCredentialsClientId: os.Getenv("FGA_CLIENT_ID"),
                ClientCredentialsClientSecret: os.Getenv("FGA_CLIENT_SECRET"),
            },
        },
    })
    if err != nil { panic(err) }
    _ = fgaClient // Use the client for the next request.
}
```

**.NET**

```csharp theme={null}
using System.Collections.Generic;
using OpenFga.Sdk.Client;
using OpenFga.Sdk.Client.Model;
using OpenFga.Sdk.Configuration;
using OpenFga.Sdk.Model;
using Environment = System.Environment;

// FGA_API_URL and FGA_API_AUDIENCE must match the store's us1/eu1/au1 region.
var fgaClient = new OpenFgaClient(new ClientConfiguration() {
  ApiUrl = Environment.GetEnvironmentVariable("FGA_API_URL"),
  StoreId = Environment.GetEnvironmentVariable("FGA_STORE_ID"),
  AuthorizationModelId = Environment.GetEnvironmentVariable("FGA_MODEL_ID"),
  Credentials = new Credentials() {
    Method = CredentialsMethod.ClientCredentials,
    Config = new CredentialsConfig() {
      ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),
      ApiAudience = Environment.GetEnvironmentVariable("FGA_API_AUDIENCE"),
      ClientId = Environment.GetEnvironmentVariable("FGA_CLIENT_ID"),
      ClientSecret = Environment.GetEnvironmentVariable("FGA_CLIENT_SECRET"),
    }
  }
});
```

**Python**

```python theme={null}
import os
from openfga_sdk.client import OpenFgaClient, ClientConfiguration
from openfga_sdk.client.models import ClientWriteRequest, ClientTuple
from openfga_sdk.models import RelationshipCondition
from openfga_sdk.client.models import ConflictOptions, ClientWriteRequestOnDuplicateWrites, ClientWriteRequestOnMissingDeletes
from openfga_sdk.credentials import Credentials, CredentialConfiguration

# FGA_API_URL and FGA_API_AUDIENCE must match the store's us1/eu1/au1 region.
credentials = Credentials(
    method='client_credentials',
    configuration=CredentialConfiguration(
        api_issuer=os.environ.get('FGA_API_TOKEN_ISSUER'),
        api_audience=os.environ.get('FGA_API_AUDIENCE'),
        client_id=os.environ.get('FGA_CLIENT_ID'),
        client_secret=os.environ.get('FGA_CLIENT_SECRET'),
    ),
)
configuration = ClientConfiguration(
    api_url=os.environ.get('FGA_API_URL'),
    store_id=os.environ.get('FGA_STORE_ID'),
    authorization_model_id=os.environ.get('FGA_MODEL_ID'),
    credentials=credentials,
)
# Use: async with OpenFgaClient(configuration) as fga_client: ...
```

**Java**

```java theme={null}
import dev.openfga.sdk.api.client.OpenFgaClient;
import dev.openfga.sdk.api.configuration.ClientConfiguration;
import dev.openfga.sdk.api.configuration.ClientCredentials;
import dev.openfga.sdk.api.configuration.Credentials;
import dev.openfga.sdk.api.configuration.ClientCheckOptions;
import dev.openfga.sdk.api.configuration.ClientBatchCheckOptions;
import dev.openfga.sdk.api.configuration.ClientWriteOptions;
import dev.openfga.sdk.api.configuration.ClientListObjectsOptions;
import dev.openfga.sdk.api.configuration.ClientListUsersOptions;
import dev.openfga.sdk.api.client.model.*;
import dev.openfga.sdk.api.model.*;
import java.util.List;
import java.util.Map;

// FGA_API_URL and FGA_API_AUDIENCE must match the store's us1/eu1/au1 region.
public class SdkSetupExample {
    public static void main(String[] args) throws Exception {
        var config = new ClientConfiguration()
            .apiUrl(System.getenv("FGA_API_URL"))
            .storeId(System.getenv("FGA_STORE_ID"))
            .authorizationModelId(System.getenv("FGA_MODEL_ID"))
            .credentials(new Credentials(new ClientCredentials()
                .apiTokenIssuer(System.getenv("FGA_API_TOKEN_ISSUER"))
                .apiAudience(System.getenv("FGA_API_AUDIENCE"))
                .clientId(System.getenv("FGA_CLIENT_ID"))
                .clientSecret(System.getenv("FGA_CLIENT_SECRET"))));
        var fgaClient = new OpenFgaClient(config);
    }
}
```

**CLI**

```bash theme={null}
# Auth0 FGA managed API: choose your store's region (us1, eu1, or au1).
export FGA_API_URL=https://api.us1.fga.dev
export FGA_API_AUDIENCE=https://api.us1.fga.dev/
export FGA_API_TOKEN_ISSUER=auth.fga.dev
export FGA_STORE_ID=YOUR_STORE_ID
export FGA_MODEL_ID=YOUR_MODEL_ID
export FGA_CLIENT_ID=YOUR_CLIENT_ID
export FGA_CLIENT_SECRET=YOUR_CLIENT_SECRET
# Obtain these values from https://dashboard.fga.dev/ and keep credentials private.
```

**curl**

To obtain the [access token](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow/call-your-api-using-the-client-credentials-flow):

```bash theme={null}
# Requires jq to safely encode credentials as JSON.
curl -sS -X POST 'https://auth.fga.dev/oauth/token' \
  -H 'content-type: application/json' \
  --data "$(jq -n \
    --arg client_id "$FGA_CLIENT_ID" \
    --arg client_secret "$FGA_CLIENT_SECRET" \
    --arg audience "$FGA_API_AUDIENCE" \
    '{client_id: $client_id, client_secret: $client_secret, audience: $audience, grant_type: "client_credentials"}')"
# Use the access_token in the response as FGA_BEARER_TOKEN for direct API calls.
```

### 02. Calling write API to add new relationship tuples

To add the relationship tuples, we can invoke the write API.

### 03. Calling write API to delete relationship tuples

To delete relationship tuples, we can invoke the write API.

Assume that you want to delete user `user:anne`'s `reader` relationship with object `document:Z`

```json theme={null}
{
  user: 'user:anne',
  relation: 'reader',
  object: 'document:Z'
}
```

### 04. Writing and deleting relationship tuples in the same request

You can combine both writes and deletes in a single transactional API request. This is useful when you need to update multiple relationships atomically. All operations in the request will either succeed together or fail together.

The Write API allows you to send up to `100` unique tuples in the request. (This limit applies to the sum of both writes and deletes in that request).

For example, you might want to remove `user:anne` as a `writer` of `document:Z` while simultaneously updating `user:anne` as an `reader` of `document:Z`:

This approach ensures that both operations succeed or fail together, maintaining transactional data consistency.

> [!NOTE]
>
> When using the Write API, you cannot include the same tuple (same user, relation, and object) in the writes or deletes arrays within a single request. The API will return an error with code `cannot_allow_duplicate_tuples_in_one_request` if detected.

### 05. Ignoring duplicate or missing tuples

Sometimes you might need to write a tuple that already exists, which would normally cause the whole request to fail. You can use the `on_duplicate: "ignore"` parameter to handle this gracefully.

This is particularly useful for high-volume data imports, migrations, or ensuring certain permissions exist without complex error handling logic.

For example, if you want to ensure `user:anne` has `reader` access to `document:Z` without worrying about whether the relationship already exists in Auth0 FGA:

Similarly, you can use `on_missing: "ignore"` when deleting tuples that might not exist.

The behavior of `on_duplicate: "ignore"` is more nuanced for tuples with conditions.

* **Identical Tuples**: If a tuple in the request is identical to an existing tuple (same user, relation, object, condition name, and condition context), it will be safely ignored.
* **Conflicting Tuples**: If a tuple key (user, relation, object) matches an existing tuple, but the condition name or parameters are different, this is a conflict. The write attempt will be rejected, and the entire transaction will fail with a `409 Conflict` error.

## Related Sections

Check the following sections for more on how to write your authorization data

[Write API
Learn more about the Write API options.](https://docs.fga.dev/api/service/relationship-tuples/write.md)

[Managing User Access
Learn about how to give a user access to a particular object.](https://docs.fga.dev/writing-data/managing-user-access.md)

[Managing Group Access
Learn about how to give a group of users access to a particular object.](https://docs.fga.dev/writing-data/managing-group-access.md)

[Transactional Writes
Learn about how to update multiple relations within the same API call.](https://docs.fga.dev/writing-data/transactional-writes.md)
