Concepts like _worn_ or _carried_ aren't built into core Evennia, but it's a common thing to add. This guide uses a `.db.worn` attribute to identify gear, but will explain how to reference your own mechanic too.
```
By default, the Evennia [REST API](../Components/Web-API.md) provides endpoints for the standard entities. One such endpoint is `/api/characters/`, returning information about Characters. In this tutorial, we'll extend it by adding an `inventory` action to the `/characters` endpoint, showing all objects being _worn_ and _carried_ by a character.
A *view* is the python code that tells django what data to put on a page, while a *template* tells django how to display that data. For more in-depth information, you can read the django [docs for views](https://docs.djangoproject.com/en/4.1/topics/http/views/) and [docs for templates](https://docs.djangoproject.com/en/4.1/topics/templates/).
```
The first thing you'll need to do is define your own `views.py` module.
The default REST API endpoints are controlled by classes in `evennia/web/api/views.py` - you could copy that entire file and use it, but we're going to focus on changing the minimum.
To start, we'll reimplement the default [CharacterViewSet](CharacterViewSet) that handles requests from the `characters/` endpoint. This is a child of the `objects` endpoint that can only access characters.
Evennia's [Game website](../Components/Website.md) page demonstrates how to use the `urls.py` module for the main website - if you haven't gone over that page yet, now is a good time.
The API routing is more complicated than the website or webclient routing, so you need to copy the entire module from evennia into your game instead of patching on changes. Copy the file from `evennia/web/api/urls.py` to your folder, `mygame/web/api/urls.py` and open it in your editor.
We've almost got it pointing at our new view now. The last step is to add your own API urls - `web.api.urls` - to your web root url module. Otherwise it will continue pointing to the default API router and we'll never see our changes.
Restart your evennia game - `evennia reboot` from the command line for a full restart of the game AND portal - and try to get `/api/characters/` again. If it works exactly like before, you're ready to move on to the next step!
Head back over to your character view class - it's time to start adding our inventory.
The usual "page" in a REST API is called an *endpoint* and is what you typically access. e.g. `/api/characters/` is the "characters" endpoint, and `/api/characters/:id` is the endpoint for individual characters.
The `:` in an API path means that it's a *variable* - you don't directly access that exact path. Instead, you'd take your character ID (e.g. 1) and use that instead: `/api/characters/1`
However, an endpoint can also have one or more *detail* views, which function like a sub-point. We'll be adding *inventory* as a detail to our character endpoint, which will look like `/api/characters/:id/inventory`
With the django REST framework, adding a new detail is as simple as adding a decorated method to the view set class - the `@action` decorator. Since checking your inventory is just data retrieval, we'll only want to permit the `GET` method, and we're adding this action as an API detail, so our decorator will look like this:
> There are situations where you might want a detail or endpoint that isn't just data retrieval: for example, *buy* or *sell* on an auction-house listing. In those cases, you would use *put* or *post* instead. For further reading on what you can do with `@action` and ViewSets, visit [the django REST framework documentation](https://www.django-rest-framework.org/api-guide/viewsets/)
When adding a function as a detail action, the name of our function will be the same as the detail. Since we want an `inventory` action we'll define an `inventory` function.
Get your character's ID - it's the same as your dbref but without the # - and then `evennia reboot` again. Now you should be able to call your new characters action: `/api/characters/1/inventory` (assuming you're looking at character #1) and it'll return the string "your inventory"
You can get a more in-depth look at django serializers in [the django REST framework serializer docs](https://www.django-rest-framework.org/api-guide/serializers/).
Generally speaking, a *serializer* turns a set of data into a specially formatted string that can be sent in a data stream - usually JSON. Django REST serializers are special classes and functions which take python objects and convert them into API-ready formats. So, just like for the viewset, django and evennia have done a lot of the heavy lifting for us already.
Instead of writing our own serializer, we'll inherit from evennia's pre-existing serializers and extend them for our own purpose. To do that, create a new file `mygame/web/api/serializers.py` and start by adding in the imports you'll need.
The `Meta` class defines which fields will be used in the final serialized string. The `id` field is from the base ModelSerializer, but you'll notice that the two others - `worn` and `carried` - are defined as properties to `SerializerMethodField`. That tells the framework to look for matching method names in the form `get_X` when serializing.
Which is why our next step is to add those methods! We defined the properties `worn` and `carried`, so the methods we'll add are `get_worn` and `get_carried`. They'll be static methods - that is, they don't include `self` - since they don't need to reference the serializer class itself.
For this guide, we're assuming that whether an object is being worn or not is stored in the `worn` db attribute and filtering based on that attribute. This can easily be done differently to match your own game's mechanics: filtering based on a tag, calling a custom method on your character that returns the right list, etc.
If you want to add in more details - grouping carried items by typing, or dividing up armor vs weapons, you'd just need to add or change the properties, fields, and methods.
> Remember: `worn = serializers.SerializerMethodField()` is how the API knows to use `get_worn`, and `Meta.fields` is the list of fields that will actually make it into the final JSON.
Go ahead and try it: `evennia reboot` and then `/api/characters/1/inventory` like before. Instead of returning the string "your inventory", you should get an error saying you don't have permission. Don't worry - that means it's successfully referencing the new serializer. We just haven't given it permission to access the objects yet.
Evennia comes with its own custom API permissions class, connecting the API permissions to the in-game permission hierarchy and locks system. Since we're trying to access the object's data now, we need to pass the `has_object_permission` check as well as the general permission check - and that default permission class hardcodes actions into the object permission checks.
Since we've added a new action - `inventory` - to our characters endpoint, we need to use our own custom permissions on our characters endpoint as well. Create one more module file: `mygame/web/api/permissions.py`
That's the whole permission class! For our final step, we need to use it in our characters view by importing it and setting the `permission_classes` property.
One last `evennia reboot` - now you should be able to get `/api/characters/1/inventory` and see everything your character has, neatly divided into "worn" and "carried".
For a more in-depth look at the django REST framework, you can go through [their tutorial](https://www.django-rest-framework.org/tutorial/1-serialization/) or straight to [the django REST framework API docs](https://www.django-rest-framework.org/api-guide/requests/).
That's it! You've learned how to customize your own REST endpoint for Evennia, add new endpoint details, and serialize data from your game's objects for the REST API. With those tools, you can take any in-game data you want and make it available - or even modifiable - with the API.
If you want a challenge, try taking what you learned and implementing a new `desc` detail that will let you `GET` the existing character desc _or_`PUT` a new desc. (Tip: check out how evennia's REST permissions module works, and the `set_attribute` methods in the default evennia REST API views.)