---
title: "Create an organisation at an address, or return the one there"
description: "Needs a platform credential: a key or token whose person holds a platform role, with the privileged tenants:write scope. A credential of an ordinary organisation member is refused whatever its scopes. The external identifier is the organisation's address, its slug. Answers 201 when it was created and 200 when it was already there.\n\n### Quire permissions\n\nCredential scopes: `tenants:write`.\n\nThe acting subject must also be allowed to perform this action in the organisation."
image: "https://docs.quirelms.com/og.png"
---

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

Path: Quire API › tenants

`PUT /tenants/ext:{external_id}`

Needs a platform credential: a key or token whose person holds a platform role, with the privileged tenants:write scope. A credential of an ordinary organisation member is refused whatever its scopes. The external identifier is the organisation's address, its slug. Answers 201 when it was created and 200 when it was already there.

\### Quire permissions

Credential scopes: `tenants:write`.

The acting subject must also be allowed to perform this action in the organisation.

## Authentication

Requires one of the following:

- `apiKey`, http, header `Authorization`, scopes: `tenants:write`
- `oauth2`, oauth2, scopes: `tenants:write`

## Path parameters

- `upsertTenant.path.external_id` (string, required) — The external identifier, unique per tenant per type, as supplied by the system of record.

## Header parameters

- `upsertTenant.header.Quire-Version` (string, optional) — The dated API revision to serve this request at. Omitted, the request is served at the revision the credential was issued against. The response echoes the revision actually applied.
  - format `date`
- `upsertTenant.header.Idempotency-Key` (string, optional) — A caller-chosen key making this request safe to retry. A replay of a completed request returns the recorded response with `Idempotency-Replayed: true`. Reusing a key for a different request is refused.
  - maxLength 255

## Request body

_Required._

- `upsertTenant.name` (string, required)
  - minLength 1; maxLength 200
- `upsertTenant.admin_email` (string, required)
  - format `email`; maxLength 254; pattern `^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$`
- `upsertTenant.admin_name` (string, required)
  - minLength 1; maxLength 200
- `upsertTenant.plan_code` (string, required)
  - minLength 1; maxLength 60
- `upsertTenant.parent_id` (any of, optional) — An organisation this one belongs under, on the same account.
  - any of: `string`, `null`
- `upsertTenant.trial` (boolean, optional)
- `upsertTenant.data_region` (string, optional)
  - minLength 2; maxLength 20

## Example request

```json
{
  "name": "string",
  "admin_email": "user@example.com",
  "admin_name": "string",
  "plan_code": "string",
  "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
  "trial": true,
  "data_region": "string"
}
```

## Code samples

### cURL

```curl
curl --request PUT \
  --url https://your-organisation.quirelms.com/api/v1/tenants/ext:string \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "name": "string",
  "admin_email": "user@example.com",
  "admin_name": "string",
  "plan_code": "string",
  "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
  "trial": true,
  "data_region": "string"
}
'
```

### TypeScript

```typescript
const url = 'https://your-organisation.quirelms.com/api/v1/tenants/ext:string';
const options = {
  method: 'PUT',
  headers: {'Content-Type': 'application/json', Authorization: 'Bearer <token>'},
  body: JSON.stringify({
    name: 'string',
    admin_email: 'user@example.com',
    admin_name: 'string',
    plan_code: 'string',
    parent_id: '1c6ca187-e61f-4301-8dcb-0e9749e89eef',
    trial: true,
    data_region: 'string'
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "https://your-organisation.quirelms.com/api/v1/tenants/ext:string"

payload = {
    "name": "string",
    "admin_email": "user@example.com",
    "admin_name": "string",
    "plan_code": "string",
    "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
    "trial": True,
    "data_region": "string"
}
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer <token>"
}

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

print(response.text)
```

## Responses

### 200

Success.

#### Example

```json
{
  "id": "string",
  "slug": "string",
  "name": "string",
  "status": "string",
  "data_region": "string",
  "parent_id": "string",
  "created_at": "string",
  "updated_at": "string"
}
```

- `upsertTenant.response.200.id` (string, required)
- `upsertTenant.response.200.slug` (string, required)
- `upsertTenant.response.200.name` (string, required)
- `upsertTenant.response.200.status` (string, required)
- `upsertTenant.response.200.data_region` (string, required)
- `upsertTenant.response.200.parent_id` (string | null, required)
- `upsertTenant.response.200.created_at` (string, required)
- `upsertTenant.response.200.updated_at` (string, required)

### 201

Success.

#### Example

```json
{
  "id": "string",
  "slug": "string",
  "name": "string",
  "status": "string",
  "data_region": "string",
  "parent_id": "string",
  "created_at": "string",
  "updated_at": "string",
  "admin_password": "string"
}
```

- `upsertTenant.response.201.id` (string, required)
- `upsertTenant.response.201.slug` (string, required)
- `upsertTenant.response.201.name` (string, required)
- `upsertTenant.response.201.status` (string, required)
- `upsertTenant.response.201.data_region` (string, required)
- `upsertTenant.response.201.parent_id` (string | null, required)
- `upsertTenant.response.201.created_at` (string, required)
- `upsertTenant.response.201.updated_at` (string, required)
- `upsertTenant.response.201.admin_password` (string | null, required) — The first administrator's password, shown once, when the address had no account yet.

### 401

The credential is missing, malformed, expired or revoked.

#### Example

```json
{
  "type": "http://example.com",
  "title": "string",
  "status": 0,
  "code": "string",
  "category": "validation",
  "detail": "string",
  "request_id": "string",
  "errors": [
    {
      "path": "string",
      "code": "string",
      "detail": "string"
    }
  ],
  "retry_after": 0,
  "docs_url": "http://example.com"
}
```

- `upsertTenant.response.401.type` (string, required)
  - format `uri`
- `upsertTenant.response.401.title` (string, required)
- `upsertTenant.response.401.status` (integer, required)
- `upsertTenant.response.401.code` (string, required)
- `upsertTenant.response.401.category` (string, required)
  - one of `"validation"`, `"authentication"`, `"authorization"`, `"not_found"`, `"conflict"`, `"precondition"`, `"quota"`, `"rate_limit"`, `"upstream"`, `"internal"`
- `upsertTenant.response.401.detail` (string, required)
- `upsertTenant.response.401.request_id` (string, required)
- `upsertTenant.response.401.docs_url` (string, required)
  - format `uri`
- `upsertTenant.response.401.errors` (array<object>, optional)
  - `upsertTenant.response.401.errors.path` (string, required) — RFC 6901 JSON Pointer into the request body.
  - `upsertTenant.response.401.errors.code` (string, required)
  - `upsertTenant.response.401.errors.detail` (string, required)
- `upsertTenant.response.401.retry_after` (integer | null, optional)

### 403

The credential lacks the scope this operation requires, or the acting subject lacks the capability.

#### Example

```json
{
  "type": "http://example.com",
  "title": "string",
  "status": 0,
  "code": "string",
  "category": "validation",
  "detail": "string",
  "request_id": "string",
  "errors": [
    {
      "path": "string",
      "code": "string",
      "detail": "string"
    }
  ],
  "retry_after": 0,
  "docs_url": "http://example.com"
}
```

- `upsertTenant.response.403.type` (string, required)
  - format `uri`
- `upsertTenant.response.403.title` (string, required)
- `upsertTenant.response.403.status` (integer, required)
- `upsertTenant.response.403.code` (string, required)
- `upsertTenant.response.403.category` (string, required)
  - one of `"validation"`, `"authentication"`, `"authorization"`, `"not_found"`, `"conflict"`, `"precondition"`, `"quota"`, `"rate_limit"`, `"upstream"`, `"internal"`
- `upsertTenant.response.403.detail` (string, required)
- `upsertTenant.response.403.request_id` (string, required)
- `upsertTenant.response.403.docs_url` (string, required)
  - format `uri`
- `upsertTenant.response.403.errors` (array<object>, optional)
  - `upsertTenant.response.403.errors.path` (string, required) — RFC 6901 JSON Pointer into the request body.
  - `upsertTenant.response.403.errors.code` (string, required)
  - `upsertTenant.response.403.errors.detail` (string, required)
- `upsertTenant.response.403.retry_after` (integer | null, optional)

### 404

No such resource, or none this credential is permitted to know about.

#### Example

```json
{
  "type": "http://example.com",
  "title": "string",
  "status": 0,
  "code": "string",
  "category": "validation",
  "detail": "string",
  "request_id": "string",
  "errors": [
    {
      "path": "string",
      "code": "string",
      "detail": "string"
    }
  ],
  "retry_after": 0,
  "docs_url": "http://example.com"
}
```

- `upsertTenant.response.404.type` (string, required)
  - format `uri`
- `upsertTenant.response.404.title` (string, required)
- `upsertTenant.response.404.status` (integer, required)
- `upsertTenant.response.404.code` (string, required)
- `upsertTenant.response.404.category` (string, required)
  - one of `"validation"`, `"authentication"`, `"authorization"`, `"not_found"`, `"conflict"`, `"precondition"`, `"quota"`, `"rate_limit"`, `"upstream"`, `"internal"`
- `upsertTenant.response.404.detail` (string, required)
- `upsertTenant.response.404.request_id` (string, required)
- `upsertTenant.response.404.docs_url` (string, required)
  - format `uri`
- `upsertTenant.response.404.errors` (array<object>, optional)
  - `upsertTenant.response.404.errors.path` (string, required) — RFC 6901 JSON Pointer into the request body.
  - `upsertTenant.response.404.errors.code` (string, required)
  - `upsertTenant.response.404.errors.detail` (string, required)
- `upsertTenant.response.404.retry_after` (integer | null, optional)

### 409

The request conflicts with the current state, with a previous use of the same idempotency key, or with a concurrent write.

#### Example

```json
{
  "type": "http://example.com",
  "title": "string",
  "status": 0,
  "code": "string",
  "category": "validation",
  "detail": "string",
  "request_id": "string",
  "errors": [
    {
      "path": "string",
      "code": "string",
      "detail": "string"
    }
  ],
  "retry_after": 0,
  "docs_url": "http://example.com"
}
```

- `upsertTenant.response.409.type` (string, required)
  - format `uri`
- `upsertTenant.response.409.title` (string, required)
- `upsertTenant.response.409.status` (integer, required)
- `upsertTenant.response.409.code` (string, required)
- `upsertTenant.response.409.category` (string, required)
  - one of `"validation"`, `"authentication"`, `"authorization"`, `"not_found"`, `"conflict"`, `"precondition"`, `"quota"`, `"rate_limit"`, `"upstream"`, `"internal"`
- `upsertTenant.response.409.detail` (string, required)
- `upsertTenant.response.409.request_id` (string, required)
- `upsertTenant.response.409.docs_url` (string, required)
  - format `uri`
- `upsertTenant.response.409.errors` (array<object>, optional)
  - `upsertTenant.response.409.errors.path` (string, required) — RFC 6901 JSON Pointer into the request body.
  - `upsertTenant.response.409.errors.code` (string, required)
  - `upsertTenant.response.409.errors.detail` (string, required)
- `upsertTenant.response.409.retry_after` (integer | null, optional)

### 422

The request was understood and its content is not valid. `errors` names each field.

#### Example

```json
{
  "type": "http://example.com",
  "title": "string",
  "status": 0,
  "code": "string",
  "category": "validation",
  "detail": "string",
  "request_id": "string",
  "errors": [
    {
      "path": "string",
      "code": "string",
      "detail": "string"
    }
  ],
  "retry_after": 0,
  "docs_url": "http://example.com"
}
```

- `upsertTenant.response.422.type` (string, required)
  - format `uri`
- `upsertTenant.response.422.title` (string, required)
- `upsertTenant.response.422.status` (integer, required)
- `upsertTenant.response.422.code` (string, required)
- `upsertTenant.response.422.category` (string, required)
  - one of `"validation"`, `"authentication"`, `"authorization"`, `"not_found"`, `"conflict"`, `"precondition"`, `"quota"`, `"rate_limit"`, `"upstream"`, `"internal"`
- `upsertTenant.response.422.detail` (string, required)
- `upsertTenant.response.422.request_id` (string, required)
- `upsertTenant.response.422.docs_url` (string, required)
  - format `uri`
- `upsertTenant.response.422.errors` (array<object>, optional)
  - `upsertTenant.response.422.errors.path` (string, required) — RFC 6901 JSON Pointer into the request body.
  - `upsertTenant.response.422.errors.code` (string, required)
  - `upsertTenant.response.422.errors.detail` (string, required)
- `upsertTenant.response.422.retry_after` (integer | null, optional)

### 429

A rate limit or a concurrency cap was reached. `Retry-After` says when to try again.

#### Example

```json
{
  "type": "http://example.com",
  "title": "string",
  "status": 0,
  "code": "string",
  "category": "validation",
  "detail": "string",
  "request_id": "string",
  "errors": [
    {
      "path": "string",
      "code": "string",
      "detail": "string"
    }
  ],
  "retry_after": 0,
  "docs_url": "http://example.com"
}
```

- `upsertTenant.response.429.type` (string, required)
  - format `uri`
- `upsertTenant.response.429.title` (string, required)
- `upsertTenant.response.429.status` (integer, required)
- `upsertTenant.response.429.code` (string, required)
- `upsertTenant.response.429.category` (string, required)
  - one of `"validation"`, `"authentication"`, `"authorization"`, `"not_found"`, `"conflict"`, `"precondition"`, `"quota"`, `"rate_limit"`, `"upstream"`, `"internal"`
- `upsertTenant.response.429.detail` (string, required)
- `upsertTenant.response.429.request_id` (string, required)
- `upsertTenant.response.429.docs_url` (string, required)
  - format `uri`
- `upsertTenant.response.429.errors` (array<object>, optional)
  - `upsertTenant.response.429.errors.path` (string, required) — RFC 6901 JSON Pointer into the request body.
  - `upsertTenant.response.429.errors.code` (string, required)
  - `upsertTenant.response.429.errors.detail` (string, required)
- `upsertTenant.response.429.retry_after` (integer | null, optional)

### 500

Something failed at our end. Quote `request_id` when reporting it.

#### Example

```json
{
  "type": "http://example.com",
  "title": "string",
  "status": 0,
  "code": "string",
  "category": "validation",
  "detail": "string",
  "request_id": "string",
  "errors": [
    {
      "path": "string",
      "code": "string",
      "detail": "string"
    }
  ],
  "retry_after": 0,
  "docs_url": "http://example.com"
}
```

- `upsertTenant.response.500.type` (string, required)
  - format `uri`
- `upsertTenant.response.500.title` (string, required)
- `upsertTenant.response.500.status` (integer, required)
- `upsertTenant.response.500.code` (string, required)
- `upsertTenant.response.500.category` (string, required)
  - one of `"validation"`, `"authentication"`, `"authorization"`, `"not_found"`, `"conflict"`, `"precondition"`, `"quota"`, `"rate_limit"`, `"upstream"`, `"internal"`
- `upsertTenant.response.500.detail` (string, required)
- `upsertTenant.response.500.request_id` (string, required)
- `upsertTenant.response.500.docs_url` (string, required)
  - format `uri`
- `upsertTenant.response.500.errors` (array<object>, optional)
  - `upsertTenant.response.500.errors.path` (string, required) — RFC 6901 JSON Pointer into the request body.
  - `upsertTenant.response.500.errors.code` (string, required)
  - `upsertTenant.response.500.errors.detail` (string, required)
- `upsertTenant.response.500.retry_after` (integer | null, optional)


Source: https://docs.quirelms.com/api/tenants/upsertTenant/index.md
