Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e5c00bb
Add Duplicate Writes documentation
tylernix Sep 10, 2025
f4bb1c5
Add Duplicate Writes documentation
tylernix Sep 10, 2025
5d6b97c
Fix linting errors in WriteRequestViewer
tylernix Sep 10, 2025
5ec0c9d
Apply manual fixes to duplicate-writes documentation
tylernix Sep 10, 2025
ab18b95
Add Duplicate Writes reference to interacting overview
tylernix Sep 10, 2025
da0d168
Remove redundant write API documentation and streamline tuple managem…
tylernix Sep 12, 2025
70d4f41
Enhance documentation with advanced tuple management and fix relation…
tylernix Sep 12, 2025
723cd19
Revert configuration.mdx changes to focus PR on tuple management docu…
tylernix Sep 12, 2025
ccefcf8
quick word fixes
tylernix Sep 12, 2025
032c06a
Revert file name from add-tuples.mdx back to update-tuples.mdx
tylernix Sep 16, 2025
227a8a9
quick fix
tylernix Sep 16, 2025
7d33e1b
Add auto-generated configuration constants and ConfigValue component
tylernix Sep 16, 2025
7aa3d8c
quick fix
tylernix Sep 16, 2025
57bbded
Fix Prettier formatting issues
tylernix Sep 16, 2025
e925c23
Fix formatting issue in auto-generated constants
tylernix Sep 16, 2025
2ba5d78
Implement generic product-config system for multi-tenant documentation
tylernix Sep 17, 2025
3947bd0
quick title fix
tylernix Sep 17, 2025
9d9447a
Remove configuration.mdx changes from PR
tylernix Sep 17, 2025
ab7802c
quick title fix
tylernix Sep 17, 2025
5998a49
Remove ConfigValue component from this PR
tylernix Sep 17, 2025
62b2d61
Merge branch 'main' into feature/duplicate-writes-docs-v3
tylernix Oct 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ It offers an HTTP API, a gRPC API, and has SDKs for programming languages includ
- [Manage Group Access](./content/interacting/managing-user-access.mdx)
- [Manage Group Membership](./content/interacting/managing-group-membership.mdx)
- [Manage Relationships Between Objects](./content/interacting/managing-relationships-between-objects.mdx)
- [Transactional Writes](./content/interacting/transactional-writes.mdx)
- [Relationship Queries](./content/interacting/relationship-queries.mdx)
- [Get Tuple Changes](./content/interacting/read-tuple-changes.mdx)
- [Search with Permissions](./content/interacting/search-with-permissions.mdx)
Expand Down
4 changes: 2 additions & 2 deletions docs/content/getting-started/perform-check.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ To obtain the [access token](https://auth0.com/docs/get-started/authentication-a

### 02. Calling Check API

To check whether user `user:anne` has relationship `can_view` with object `document:Z`
To check whether user `user:anne` has relationship `reader` with object `document:Z`

<CheckRequestViewer
user={'user:anne'}
relation={'can_view'}
relation={'reader'}
object={'document:Z'}
allowed={true}
skipSetup={true}
Expand Down
120 changes: 108 additions & 12 deletions docs/content/getting-started/update-tuples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Update Relationship Tuples
sidebar_position: 3
slug: /getting-started/update-tuples
description: Updating system state by writing and deleting relationship tuples
description: Introduction to adding and deleting relationship tuples
---

import {
Expand All @@ -24,7 +24,7 @@ import TabItem from '@theme/TabItem';

<DocumentationNotice />

This section will illustrate how to update _<ProductConcept section="what-is-a-relationship-tuple" linkName="relationship tuples" />_.
This is an introduction to adding and deleting _<ProductConcept section="what-is-a-relationship-tuple" linkName="relationship tuples" />_.

## Before you start

Expand Down Expand Up @@ -93,7 +93,7 @@ Assume that you want to add user `user:anne` to have relationship `reader` with
{
user: 'user:anne',
relation: 'reader',
object: 'document:Z',
object: 'document:Z'
}
```

Expand Down Expand Up @@ -150,7 +150,7 @@ To add the relationship tuples, we can invoke the write API.
{
user: 'user:anne',
relation: 'reader',
object: 'document:Z',
object: 'document:Z'
},
]}
skipSetup={true}
Expand All @@ -175,7 +175,7 @@ Assume that you want to delete user `user:anne`'s `reader` relationship with obj
{
user: 'user:anne',
relation: 'reader',
object: 'document:Z',
object: 'document:Z'
}
```

Expand All @@ -184,7 +184,7 @@ Assume that you want to delete user `user:anne`'s `reader` relationship with obj
{
user: 'user:anne',
relation: 'reader',
object: 'document:Z',
object: 'document:Z'
},
]}
skipSetup={true}
Expand All @@ -199,11 +199,113 @@ Assume that you want to delete user `user:anne`'s `reader` relationship with obj
]}
/>

### 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`:

<WriteRequestViewer
relationshipTuples={[
{
user: 'user:anne',
relation: 'reader',
object: 'document:Z'
},
]}
deleteRelationshipTuples={[
{
user: 'user:anne',
relation: 'writer',
object: 'document:Z'
},
]}
skipSetup={true}
allowedLanguages={[
SupportedLanguage.JS_SDK,
SupportedLanguage.GO_SDK,
SupportedLanguage.DOTNET_SDK,
SupportedLanguage.PYTHON_SDK,
SupportedLanguage.JAVA_SDK,
SupportedLanguage.CLI,
SupportedLanguage.CURL,
]}
/>

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 <ProductName format={ProductNameFormat.ShortForm}/>:

<WriteRequestViewer
relationshipTuples={[
{
user: 'user:anne',
relation: 'reader',
object: 'document:Z'
},
]}
writeOptions={{
on_duplicate: 'ignore',
}}
skipSetup={true}
allowedLanguages={[
SupportedLanguage.CURL,
]}
/>

:::caution
At the moment, this feature is only available on the API (v1.10.0). Supported SDKs will follow shortly after.
:::

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

<WriteRequestViewer
skipSetup={true}
deleteRelationshipTuples={[
{
user: 'user:anne',
relation: 'writer',
object: 'document:Z'
},
]}
deleteOptions={{
on_missing: 'ignore',
}}
expectedResponse={{
data: {},
}}
allowedLanguages={[
SupportedLanguage.CURL,
]}
/>

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

<RelatedSection
description="Check the following sections for more on how to write your authorization data"
relatedLinks={[
{
title: 'Write API',
description: 'Learn more about the Write API options.',
link: '/api/service#Relationship%20Tuples/Write',
},
{
title: 'Managing User Access',
description: 'Learn about how to give a user access to a particular object.',
Expand All @@ -216,11 +318,5 @@ Assume that you want to delete user `user:anne`'s `reader` relationship with obj
link: '../interacting/managing-group-access',
id: '../interacting/managing-group-access.mdx',
},
{
title: 'Transactional Writes',
description: 'Learn about how to update multiple relations within the same API call.',
link: '../interacting/transactional-writes',
id: '../interacting/transactional-writes.mdx',
},
]}
/>
5 changes: 0 additions & 5 deletions docs/content/interacting/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ This section helps you integrate <ProductName format={ProductNameFormat.ShortFor
'Write relationship tuples to manage how two objects are related. E.g. parent folder and child document.',
to: 'interacting/managing-relationships-between-objects',
},
{
title: 'Transactional Writes',
description: 'Write multiple relationship tuples in a single request, so all writes either succeed or fail.',
to: 'interacting/transactional-writes',
},
{
title: 'Relationship Queries',
description: 'An overview of how to use the Check, Read, Expand, and ListObject APIs.',
Expand Down
Loading
Loading