<@U04UQ68083H> Is it possible to create more than ...
# ory-copilot
c
@chilly-king-10285 Is it possible to create more than one tuple using Ory Keto or the Ory Permissions API with the exact same values?
c
A message from kapa.ai
No. Relation tuples are modeled as unique relationships (namespace, object, relation, subject). Write operations either insert if not present or are ignored if the exact tuple already exists, and deletes are ignored if it doesn’t exist. In the transactional write API, ACTION_INSERT “is ignored if already existing,” preventing duplicates. [[write proto](https://www.ory.sh/docs/keto/reference/proto-api#oryketorelation_tuplesv1alpha2write_serviceproto)]
c
You say “ignored”, but does it return an error code 429, 422, or 400?
@chilly-king-10285 You say “ignored”, but does it return an error code 429, 422, or 400?
c
A message from kapa.ai
The docs indicate duplicate inserts are “ignored if already existing,” but they don’t specify a special error like 429/422/400 for that case. The transactional Write API defines ACTION_INSERT as ignored when the tuple exists; no error behavior is described there. [[write proto](https://www.ory.sh/docs/keto/reference/proto-api#oryketorelation_tuplesv1alpha2write_serviceproto)] For REST: - PATCH /admin/relation-tuples returns 204 on success; 400/404 are generic error formats, but there’s no mention of a duplicate-insert error. [[patchRelationships](https://raw.githubusercontent.com/ory/keto/master/spec/api.json)] - PUT /admin/relation-tuples returns 201 on creation; error schemas are generic and do not call out duplicates. [[createRelationship (Keto)](https://raw.githubusercontent.com/ory/keto/master/spec/api.json); [createRelationship (Ory API)](https://raw.githubusercontent.com/ory/docs/master/docs/reference/api.json)] So, based on the available sources, duplicates are ignored without a specific 429/422/400 for “already exists.” The knowledge sources do not explicitly state the exact HTTP status returned when an insert is ignored.
c
@chilly-king-10285 So if a request is made to the Ory Permission API to create a tuple, and that exact tuple already exists, the API does not return any code or error message or indication of any kind that the operation has failed because the requested tuple already exists?
c
A message from kapa.ai
Short answer: the docs don’t guarantee a “duplicate” error or status. - Transactional gRPC writes: ACTION_INSERT “is ignored if already existing.” No error or special status is defined there. [[write proto](https://www.ory.sh/docs/keto/reference/proto-api#oryketorelation_tuplesv1alpha2write_serviceproto)] - REST writes: - PUT /admin/relation-tuples (create): documents 201 on creation and generic error schemas, but does not specify a distinct response for “already exists.” [[createRelationship (Keto)](https://raw.githubusercontent.com/ory/keto/master/spec/api.json); [createRelationship (Ory API)](https://raw.githubusercontent.com/ory/docs/master/docs/reference/api.json)] - PATCH /admin/relation-tuples: returns 204 on success; errors are generic, no duplicate-specific code is mentioned. [[patchRelationships](https://raw.githubusercontent.com/ory/keto/master/spec/api.json)] Therefore, based on the provided sources, if the exact tuple already exists, the operation is “ignored” and the docs do not state that you will receive a specific error code or indication of failure. The knowledge sources do not explicitly specify the exact HTTP status returned in that case. [[write proto](https://www.ory.sh/docs/keto/reference/proto-api#oryketorelation_tuplesv1alpha2write_serviceproto)]
c
@chilly-king-10285 Can you provide an example using Golang that illustrates how to handle an API request to create a tuple using Ory Permissions API and also handle a response that “somehow” indicates that the tuple already exists.
c
A message from kapa.ai
Below is a minimal Go example using the Ory Permissions (REST) SDK that: - Tries to create a relationship tuple. - Checks the HTTP response to “infer” a duplicate (because the docs don’t specify a dedicated duplicate status). Practically, you can: - Treat 201 as created. - If you get a 400+ error, surface it. - Optionally, perform a follow-up CheckPermission to verify the tuple already exists, which “indicates” it was a no-op if creation didn’t return 201. The sources do not guarantee a specific status for duplicates. [[Permissions Go SDK](https://www.ory.sh/docs/keto/sdk/go); [createRelationship](https://www.ory.sh/docs/guides/upgrade/sdk-v1#permissions--access-control); [createRelationship API](https://raw.githubusercontent.com/ory/docs/master/docs/reference/api.json)]
Copy code
go package main  import (  "context"  "fmt"  "net/http"  "os"   ory "<http://github.com/ory/client-go|github.com/ory/client-go>" )  func main() {  // Example tuple: Blog:secret_post#view@Bob  namespace := "Blog"  object := "secret_post"  relation := "view"  subjectId := "Bob"   // Auth: export ORY_API_KEY before running  ctx := context.WithValue(context.Background(), ory.ContextAccessToken, os.Getenv("ORY_API_KEY"))   // Point to your Ory Network project URL  cfg := ory.NewConfiguration()  cfg.Servers = []ory.ServerConfiguration{{   URL: "<https://your-project.slug.projects.oryapis.com>",  }}  api := ory.NewAPIClient(cfg)   // Prepare create payload  body := ory.CreateRelationshipBody{   Namespace: &namespace,   Object:    &object,   Relation:  &relation,   SubjectId: &subjectId,  }   // Attempt to create the relationship  _, resp, err := api.RelationshipApi.   CreateRelationship(ctx).   CreateRelationshipBody(body).   Execute()   if err != nil {   // We don't have a documented "duplicate" code; handle generically.   // If you want to detect "already exists", do a follow-up check below.   fmt.Printf("CreateRelationship error: %v (status: %v)\n", err, statusOf(resp))  } else {   // Typically 201 when created   fmt.Printf("CreateRelationship success (status: %v)\n", statusOf(resp))  }   // “Somehow indicate” it already exists:  // Perform a permission check. If allowed == true, the tuple is present,  // meaning either it was created now or it already existed (duplicate no-op).  check, resp2, err2 := api.PermissionApi.   CheckPermission(ctx).   Namespace(namespace).   Object(object).   Relation(relation).   SubjectId(subjectId).   Execute()  if err2 != nil {   fmt.Printf("CheckPermission error: %v (status: %v)\n", err2, statusOf(resp2))   return  }   if check.GetAllowed() {   // At this point, you can treat this as “tuple exists”.   // If CreateRelationship did not return 201 above, this likely indicates it already existed.   fmt.Println("Tuple exists (permission allowed) — either created just now or already present.")  } else {   fmt.Println("Tuple does not exist (permission denied).")  } }  func statusOf(r *http.Response) int {  if r == nil {   return 0  }  return r.StatusCode }
Notes: - The SDK method names and flow are based on the Ory Permissions (client-go) examples for CreateRelationship and CheckPermission. [[Permissions Go SDK](https://www.ory.sh/docs/keto/sdk/go)] - The upgrade guide shows the module/method names (RelationshipApi.CreateRelationship, PermissionApi.CheckPermission). [[SDK upgrade](https://www.ory.sh/docs/guides/upgrade/sdk-v1#permissions--access-control)] - The API references document CreateRelationship but do not specify a distinct “duplicate” status; duplicates are “ignored” in the gRPC write semantics, so the follow-up CheckPermission is a reliable way to confirm existence. [[createRelationship API](https://raw.githubusercontent.com/ory/docs/master/docs/reference/api.json); [write proto](https://www.ory.sh/docs/keto/reference/proto-api#oryketorelation_tuplesv1alpha2write_serviceproto)]
c
@chilly-king-10285 So there is no reliable way to guard against the creation of duplicate tuples created via the Ory Permissions API?
c
A message from kapa.ai
Short answer: correct—there’s no documented, reliable “duplicate detected” signal from the Ory Permissions/Keto APIs. - gRPC writes: ACTION_INSERT “is ignored if already existing,” and no error or special status is defined for duplicates. [[write proto](https://www.ory.sh/docs/keto/reference/proto-api#oryketorelation_tuplesv1alpha2write_serviceproto)] - REST writes: the create endpoints document normal success/error statuses but do not specify a distinct status for “already exists.” [[createRelationship](https://raw.githubusercontent.com/ory/docs/master/docs/reference/api.json)] Practically, to guard against duplicates you must design idempotency on the client side (e.g., check-before-insert, or accept that duplicate inserts are no-ops and verify existence via CheckPermission), since the API itself does not guarantee a duplicate-specific response. [[API overview](https://www.ory.sh/docs/keto/concepts/api-overview); [write proto](https://www.ory.sh/docs/keto/reference/proto-api#oryketorelation_tuplesv1alpha2write_serviceproto)]
c
@magnificent-energy-493 @early-magician-18981 👆
👀 1