# Services

> When building extensions, you may use internal Directus services directly.

API extensions can directly use internal Directus services like the `ItemsService`, `CollectionsService`, `FilesService`, and more, accessible through the `context` parameter.

When initializing services, you will need the following:

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        schema
      </code>
    </td>
    
    <td>
      The database schema, provided by the <code>
        getSchema
      </code>
      
       function.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        accountability
      </code>
    </td>
    
    <td>
      Accountability object, used for access control. Omission or <code>
        null
      </code>
      
       will use administrator permissions.
    </td>
  </tr>
</tbody>
</table>

<callout icon="i-lucide-link" to="https://github.com/directus/directus/tree/main/api/src/services">

See a complete list of all services available by looking at the Directus source code.

</callout>

This page uses endpoints to demonstrate how to use services, but they can also be used in other API extension types.

<callout icon="i-lucide-triangle-alert" color="warning">

**Infinite Recursion**
If you are listening to an event and your handler is emitting the same event, you will need to pass `{ emitEvents: false }` in order to prevent infinite recursion.

</callout>

## `ItemsService`

```js
export default (router, context) => {
    const { services, getSchema } = context;
    const { ItemsService } = services;

    router.get('/', async (req, res) => {
        const itemsService = new ItemsService('collection_name', {
            schema: await getSchema(),
            accountability: req.accountability
        });

        // Your route handler logic
    });
};
```

### Create an Item

```js
const data = await itemsService.createOne({
    title: 'Hello world!',
    body: 'This is our first article',
});
```

### Read an Item

```js
const data = await itemsService.readOne('item_id');
```

### Update an Item

```js
const data = await itemsService.updateOne('item_id', {
    title: "An updated title"
});
```

### Delete an Item

```js
const data = await itemsService.deleteOne('item_id');
```

<callout icon="i-lucide-link" to="https://github.com/directus/directus/blob/main/api/src/services/items.ts">

See a complete list of all methods in the `ItemsService` by looking at the Directus source code.

</callout>

## `CollectionsService`

```js
export default (router, context) => {
    const { services, getSchema } = context;
    const { CollectionsService } = services;

    router.get('/', async (req, res) => {
        const collectionsService = new CollectionsService({
            schema: await getSchema(),
            accountability: req.accountability
        });

        // Your route handler logic
    });
};
```

### Create a Collection

```js
const data = await collectionsService.createOne({
    name: 'articles',
    meta: {
        note: 'Blog posts.',
    },
});
```

### Read a Collection

```js
const data = await collectionsService.readOne('collection_name');
```

### Update a Collection

```js
const data = await collectionsService.updateOne('collection_name', {
    meta: {
        note: 'Updated blog posts.',
    },
});
```

### Delete a Collection

```js
const data = await collectionsService.deleteOne('collection_name');
```

<callout icon="i-lucide-link" to="https://github.com/directus/directus/blob/main/api/src/services/collections.ts">

See a complete list of all methods in the `CollectionsService` by looking at the Directus source code.

</callout>

## `FieldsService`

```js
export default (router, context) => {
    const { services, getSchema } = context;
    const { FieldsService } = services;

    router.get('/', async (req, res) => {
        const fieldsService = new FieldsService({
            schema: await getSchema(),
            accountability: req.accountability
        });

        // Your route handler logic
    });
}
```

### Create a Field

```js
await fieldsService.createField('collection_name', {
    field: 'title',
    type: 'string',
    meta: {
        icon: 'title',
    },
    schema: {
        default_value: 'Hello World',
    },
});
```

### Read a Field

```js
const data = await fieldsService.readOne('collection_name', 'field_name');
```

### Update a Field

```js
const data = await fieldsService.updateField('collection_name', {
    field:  'field_name',
    meta: {
        icon: 'title',
    },
});
```

<callout icon="i-lucide-info">

You cannot update the field name via Directus after creating the field.

</callout>

### Delete a Field

```js
const data = await fieldsService.deleteField('collection_name', 'field_name');
```

## `RelationsService`

```js
export default (router, context) => {
  const { services, getSchema } = context;
  const { RelationsService } = services;

  router.get('/', async (req, res) => {
    const relationsService = new RelationsService({
      schema: await getSchema(),
      accountability: req.accountability
    });

    // Your route handler logic
  });
};
```

### Create a Relation

```js
const data = await relationsService.createOne({
    collection: 'articles',
    field: 'featured_image',
    related_collection: 'directus_files',
});
```

### Read a Relation

```js
const data = await relationsService.readOne('collection_name', 'field_name');
```

### Update a Relation

```js
const data = await relationsService.updateOne(
    'collection_name',
    'field_name',
    {
        meta: {
            one_field: 'articles',
        },
    },
);
```

### Delete a Relation

```js
const data = await relationsService.deleteOne('collection_name', 'field_name' );
```

<callout icon="i-lucide-link" to="https://github.com/directus/directus/blob/main/api/src/services/relations.ts">

See a complete list of all methods in the `RelationsService` by looking at the Directus source code.

</callout>

## `FilesService`

```js
export default (router, context) => {
    const { services, getSchema } = context;
    const { FilesService } = services;

    router.get('/', async (req, res) => {
        const filesService = new FilesService({
            schema: await getSchema(),
            accountability: req.accountability
        });

        // Your route handler logic
    });
};
```

### Import a File

```js
const assetKey = await filesService.importOne(file_url, file_object);
```

### Upload a File

Uploading a file requires the use of an external dependency called *Busboy*, a streaming parser for Node.js. Import it at the top of your extension:

```js
import Busboy from 'busboy'
```

Then, inside of the route handler, pipe the request into Busboy:

```js
const busboy = Busboy({ headers: req.headers });

busboy.on('file', async (_, fileStream, { filename, mimeType }) => {
    const primaryKey = await filesService.uploadOne(fileStream, {
        filename_download: filename,
        type: mimeType,
        storage: 'local',
    });
});

req.pipe(busboy);
```

### Read a File

```js
const data = await filesService.readOne('file_id');
```

### Update a File

```js
const data = await filesService.updateOne('file_id', { title: 'Random' });
```

### Delete a File

```js
const data = await filesService.deleteOne('file_id');
```

<callout icon="i-lucide-link" to="https://github.com/directus/directus/blob/main/api/src/services/files.ts">

See a complete list of all methods in the `FilesService` by looking at the Directus source code.

</callout>
