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

# Doohick Resources API: Create, List, Update, and Delete

> Create, read, update, and delete Doohick resources via the REST API. Manage resource metadata, status, and workspace assignments programmatically.

The Resources API provides full CRUD access to the resources in your Doohick workspace. Resources are the core objects you configure and track on the platform — use this API to create them programmatically, query their current state, update their metadata, or permanently remove them. All requests must include a valid Bearer token in the `Authorization` header.

***

## `POST /resources`

Create a new resource in your workspace. Supply a `name` and `type` at minimum; attach arbitrary key-value metadata to keep your resources organized.

<ParamField body="name" type="string" required>
  A human-readable label for the resource. Must be between 1 and 255 characters.
</ParamField>

<ParamField body="type" type="string" required>
  The resource type. Accepted values are `standard`, `premium`, and `custom`. This field cannot be changed after creation.
</ParamField>

<ParamField body="metadata" type="object">
  An optional key-value object for storing additional context, such as environment tags or internal identifiers. All keys and values must be strings.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.doohick.com/v1/resources \
    -H "Authorization: Bearer dh_live_XXXXXXXXXXXXXXXXXXXX" \
    -H "Content-Type: application/json" \
    -d '{"name": "My Resource", "type": "standard", "metadata": {"env": "production"}}'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.doohick.com/v1/resources', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'My Resource',
      type: 'standard',
      metadata: { env: 'production' }
    })
  });

  const { data } = await response.json();
  console.log(data.id);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.doohick.com/v1/resources',
      headers={
          'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX',
          'Content-Type': 'application/json'
      },
      json={
          'name': 'My Resource',
          'type': 'standard',
          'metadata': {'env': 'production'}
      }
  )

  data = response.json()['data']
  print(data['id'])
  ```
</CodeGroup>

**Response `201 Created`**

```json JSON theme={null}
{
  "data": {
    "id": "res_xyz789",
    "name": "My Resource",
    "type": "standard",
    "status": "active",
    "metadata": { "env": "production" },
    "workspace_id": "ws_abc123",
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T10:00:00Z"
  }
}
```

<ResponseField name="data" type="object" required>
  The newly created resource object.

  <Expandable title="data">
    <ResponseField name="id" type="string">
      Unique identifier for the resource, prefixed with `res_`.
    </ResponseField>

    <ResponseField name="name" type="string">
      The display name of the resource.
    </ResponseField>

    <ResponseField name="type" type="string">
      The resource type set at creation. One of `standard`, `premium`, or `custom`.
    </ResponseField>

    <ResponseField name="status" type="string">
      Current lifecycle status of the resource. One of `active` or `archived`.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      The key-value metadata object attached to this resource.
    </ResponseField>

    <ResponseField name="workspace_id" type="string">
      The ID of the workspace that owns this resource.
    </ResponseField>

    <ResponseField name="created_at" type="string">
      ISO 8601 timestamp indicating when the resource was created.
    </ResponseField>

    <ResponseField name="updated_at" type="string">
      ISO 8601 timestamp indicating when the resource was last modified.
    </ResponseField>
  </Expandable>
</ResponseField>

***

## `GET /resources`

List all resources in your workspace. Filter by `status` or `type` and paginate through results using `limit` and `offset`.

<ParamField query="limit" type="integer" default="20">
  The maximum number of resources to return. Accepted range is `1`–`100`.
</ParamField>

<ParamField query="offset" type="integer" default="0">
  The number of resources to skip before returning results.
</ParamField>

<ParamField query="status" type="string">
  Filter resources by lifecycle status. Pass `active` to return only active resources, or `archived` to return only archived ones. Omit to return all.
</ParamField>

<ParamField query="type" type="string">
  Filter resources by type. Accepted values are `standard`, `premium`, and `custom`.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.doohick.com/v1/resources?limit=20&offset=0&status=active" \
    -H "Authorization: Bearer dh_live_XXXXXXXXXXXXXXXXXXXX"
  ```

  ```javascript Node.js theme={null}
  const params = new URLSearchParams({ limit: '20', offset: '0', status: 'active' });
  const response = await fetch(`https://api.doohick.com/v1/resources?${params}`, {
    headers: { 'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX' }
  });

  const { data, meta } = await response.json();
  console.log(`${meta.total} total resources`);
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://api.doohick.com/v1/resources',
      headers={'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX'},
      params={'limit': 20, 'offset': 0, 'status': 'active'}
  )

  result = response.json()
  print(f"{result['meta']['total']} total resources")
  ```
</CodeGroup>

**Response `200 OK`**

```json JSON theme={null}
{
  "data": [
    {
      "id": "res_xyz789",
      "name": "My Resource",
      "type": "standard",
      "status": "active",
      "metadata": { "env": "production" },
      "workspace_id": "ws_abc123",
      "created_at": "2024-01-15T10:00:00Z",
      "updated_at": "2024-01-15T10:00:00Z"
    }
  ],
  "meta": {
    "total": 15,
    "limit": 20,
    "offset": 0
  }
}
```

***

## `GET /resources/{id}`

Retrieve a single resource by its ID. Replace `{id}` in the path with the resource's `res_` prefixed identifier.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://api.doohick.com/v1/resources/res_xyz789 \
    -H "Authorization: Bearer dh_live_XXXXXXXXXXXXXXXXXXXX"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.doohick.com/v1/resources/res_xyz789', {
    headers: { 'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX' }
  });

  const { data } = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      'https://api.doohick.com/v1/resources/res_xyz789',
      headers={'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX'}
  )

  data = response.json()['data']
  print(data)
  ```
</CodeGroup>

**Response `200 OK`**

```json JSON theme={null}
{
  "data": {
    "id": "res_xyz789",
    "name": "My Resource",
    "type": "standard",
    "status": "active",
    "metadata": { "env": "production" },
    "workspace_id": "ws_abc123",
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T10:00:00Z"
  }
}
```

<Note>
  The API returns a `404 Not Found` error if the resource ID does not exist in your workspace or belongs to a different workspace.
</Note>

***

## `PUT /resources/{id}`

Update an existing resource's `name` or `metadata`. Pass only the fields you want to change — omitted fields retain their current values.

<ParamField body="name" type="string">
  A new display name for the resource.
</ParamField>

<ParamField body="metadata" type="object">
  A replacement metadata object. This fully overwrites the existing metadata; perform a read-modify-write if you need to preserve existing keys.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT https://api.doohick.com/v1/resources/res_xyz789 \
    -H "Authorization: Bearer dh_live_XXXXXXXXXXXXXXXXXXXX" \
    -H "Content-Type: application/json" \
    -d '{"name": "Updated Resource", "metadata": {"env": "staging", "version": "2"}}'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.doohick.com/v1/resources/res_xyz789', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'Updated Resource',
      metadata: { env: 'staging', version: '2' }
    })
  });

  const { data } = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  response = requests.put(
      'https://api.doohick.com/v1/resources/res_xyz789',
      headers={
          'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX',
          'Content-Type': 'application/json'
      },
      json={'name': 'Updated Resource', 'metadata': {'env': 'staging', 'version': '2'}}
  )

  data = response.json()['data']
  print(data)
  ```
</CodeGroup>

**Response `200 OK`**

The response returns the full updated resource object with the same shape as `GET /resources/{id}`.

***

## `DELETE /resources/{id}`

Permanently delete a resource by its ID. A successful request returns `204 No Content` with an empty body.

<Warning>
  Deletion is permanent and cannot be undone. All data associated with the resource, including its metadata and event history, is immediately and irreversibly removed. Archive the resource instead if you need to retain its history.
</Warning>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://api.doohick.com/v1/resources/res_xyz789 \
    -H "Authorization: Bearer dh_live_XXXXXXXXXXXXXXXXXXXX"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.doohick.com/v1/resources/res_xyz789', {
    method: 'DELETE',
    headers: { 'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX' }
  });

  if (response.status === 204) {
    console.log('Resource deleted successfully.');
  }
  ```

  ```python Python theme={null}
  import requests

  response = requests.delete(
      'https://api.doohick.com/v1/resources/res_xyz789',
      headers={'Authorization': 'Bearer dh_live_XXXXXXXXXXXXXXXXXXXX'}
  )

  if response.status_code == 204:
      print('Resource deleted successfully.')
  ```
</CodeGroup>

**Response `204 No Content`**

The response body is empty on success.
