# Resource Status

**URL:** <https://discuss.jsonapi.org/t/resource-status/1516>\
**Category:** Uncategorized\
**Created:** [February 12, 2019, 9:49pm UTC](https://discuss.jsonapi.org/t/resource-status/1516 "2019-02-12T21:49:12Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [February 12, 2019, 9:49pm UTC](https://discuss.jsonapi.org/t/resource-status/1516/1 "2019-02-12T21:49:12Z")

</div>

Recently I’ve faced controversial point.

I have a resource, let’s call it `Product`. And it’s got attribute `state` which could be: `Draft` or `Active`.  
When it’s in `Draft` state - you are allowed to PATCH any attributes and relationships of the Resource. But once it enters `Active` state - you can PATCH only its prices relationship.

```auto
{
    "data": {
        "type": "Product",
        "id": "product-4",
        "attributes": {
            "state": "Draft",
            "name": "Super Product"
        },
        "relationships": {
            "prices": {
                "data": [
                    {
                        "type": "Price",
                        "id": "price-1"
                    }
                ]
            },
            "suppliers": {
                "data": [
                    {
                        "type": "Supplier",
                        "id": "supplier-2"
                    }
                ]
            }
        }
    }
}

```

What is the best way to describe such behavior? ALPS?

---

<div class="post-metadata">

**Author:** ![maark](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/maark/32/184_2.png) [@maark](https://discuss.jsonapi.org/u/maark)\
**Post date:** [February 12, 2019, 10:08pm UTC](https://discuss.jsonapi.org/t/resource-status/1516/2 "2019-02-12T22:08:16Z")

</div>

Isn’t that specific to the implementation of the `PATCH /products/id` endpoint?

You just check `state` and the fields being updated and allow it or return an error.

Is that something that should be covered by JSON:API?

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [February 12, 2019, 10:14pm UTC](https://discuss.jsonapi.org/t/resource-status/1516/3 "2019-02-12T22:14:37Z")

</div>

It’s common for any API. What I want to achieve: let client to know what they can do with resource. Errors or ignoring change is reactive solution, which must be implemented for sure, but I’m talking about some kind of proactive solution. Interface which client application could rely to display only fields which are available to change.

---

<div class="post-metadata">

**Author:** ![maark](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/maark/32/184_2.png) [@maark](https://discuss.jsonapi.org/u/maark)\
**Post date:** [February 15, 2019, 12:45am UTC](https://discuss.jsonapi.org/t/resource-status/1516/4 "2019-02-15T00:45:40Z")

</div>

Could you give me an example of how an API can let the user know what they can do with a resource? It would help me understand your problem.

---

<div class="post-metadata">

**Author:** ![cmeeren](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/cmeeren/32/596_2.png) [@cmeeren](https://discuss.jsonapi.org/u/cmeeren)\
**Post date:** [February 17, 2019, 8:16am UTC](https://discuss.jsonapi.org/t/resource-status/1516/5 "2019-02-17T08:16:05Z")

</div>

We have the same thing in our API: A resource can exist in several different general states, and some states do not allow the resource to be modified, while others may allow some fields or operations.

What we did was this:

- Attribute-specific constraints: The relevant resources have an attribute `constraints`. This is an object whose properties is a subset of the resoure’s attributes, but each of these `constraint` sub-properties has the same structure:

- When it comes to whether PATCH is allowed at all: We just have a property `isReadonly` on the resource that, when `true`, indicates that PATCH is not possible. (Strictly speaking we have a `readonlyReason` that when `null` allows PATCH, and when not `null` provides a machine-parsable reason why PATCH is not allowed. Note that other custom operations may be allowed which may then put the resource in a state that allows PATCH.)

- We have a similar attribute called `canDelete`.

- When it comes to other operations (custom links), they are simply allowed if and only if the links exist.

All of the above is specified clearly in our API specification. AFAIK JSON-API specifies no standards for these use-cases.

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [February 17, 2019, 8:34pm UTC](https://discuss.jsonapi.org/t/resource-status/1516/6 "2019-02-17T20:34:37Z")

</div>

Thanks for sharing. Seems interesting. It could be placed in `meta`.

---

<div class="post-metadata">

**Author:** ![cmeeren](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/cmeeren/32/596_2.png) [@cmeeren](https://discuss.jsonapi.org/u/cmeeren)\
**Post date:** [February 17, 2019, 9:18pm UTC](https://discuss.jsonapi.org/t/resource-status/1516/7 "2019-02-17T21:18:18Z")

</div>

Yes, I considered that originally, but ultimately I decided that it was semantically just normal attributes (e.g. you could just as well have attributes `count`, `countWritable`, `countMin`, `countMax`, etc.). It made more sense to me to just have the constraints under `attributes` (but in a separate `constraints` container that could be excluded as a whole using sparse fieldsets, and to not clutter up the attributes list).

Plus, considering our stack, it would be higher friction to use `meta` extensively.

---

<div class="post-metadata">

**Author:** ![rickardoberg](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/rickardoberg/32/594_2.png) [@rickardoberg](https://discuss.jsonapi.org/u/rickardoberg)\
**Post date:** [February 18, 2019, 5:42am UTC](https://discuss.jsonapi.org/t/resource-status/1516/8 "2019-02-18T05:42:55Z")

</div>

So I had the same issue. In our case all state transitions are explicit, so main resources only support GET. What we then did was to have each resource emit a JSON Schema which lists all possible attributes plus all possible state transitions as links in the resource, with inline schema. Example:  
{  
“$schema”: “[http://json-schema.org/draft-07/schema#](http://json-schema.org/draft-07/schema#)”,  
“type”: “object”,  
“definitions”: {  
“resource”: {  
“type”: “object”,  
“required”: [  
“type”,  
“id”  
],  
“additionalProperties”: false,  
“properties”: {  
“type”: {  
“type”: “string”,  
“const”: “thread”  
},  
“id”: {  
“type”: “string”  
},  
“attributes”: {  
“$ref”: “#/definitions/attributes”  
}  
}  
},  
“attributes”: {  
“type”: “object”,  
“additionalProperties”: false,  
“required”: [  
…stuff…  
],  
“properties”: {  
…stuff…  
}  
}  
},  
“properties”: {  
“data”: {  
“$ref”: “#/definitions/resource”  
}  
},  
“links”: [  
{  
“rel”: “likevideo”,  
“href”: “{+command\_href}”,  
“templateRequired”: [  
“command\_href”  
],  
“submissionMediaType”: “application/vnd.api+json”,  
“submissionSchema”: {  
“type”: “object”,  
“properties”: {  
“data”: {  
“type”: “object”,  
“properties”: {  
“attributes”: {  
“type”: “object”,  
“required”: [  
],  
“properties”: {  
}  
}  
}  
}  
}  
},  
“targetPointers”: {  
“command\_href”: “/data/links/likevideo”  
}  
}, … more actions …  
]  
}

The trick is that the action href needs to be resolved against the actual JSON API document. So the schema shows all possible actions, including developer notes and such documentation (not included above), and is designed to be highly cacheable, but the actual actions available will be determined by the links section in the resource object. The href for the action will be to the same resource URL but with an additional ?profile= parameter. For POSTs (submissions) the client just post the data there, given that it knows what attributes should be in there based on the schema, and for PATCHes (updates) the client would do a GET first to see current state, update that, then PATCH it in.

With this approach we get explicit state transitions, client always knows exactly what is doable given current state, and what to submit, and we have a clear separation between the static schema (what is possible) and the individual current resource state (current attributes and links to available actions). At this point I don’t see us using the resource relationships feature in JSON API at all, and instead rely on explicit state transitions to model those. For example, if a resource had e.g. “…/relationships/comments” as a relationships resource, there are still tons of rules for whether a user can actually post a comment to that, which needs to be surfaced, and so we would just do that on “…/comments” resource instead. No implicit state transitions allowed basically.

For our purposes this is precisely what we need. The main trick was to figure out how to get JSON API and JSON Schema to each provide their different strengths between static and dynamic data.

---

<div class="post-metadata">

**Author:** ![systemovich](https://avatars.discourse-cdn.com/v4/letter/s/b4bc9f/32.png) [@systemovich](https://discuss.jsonapi.org/u/systemovich)\
**Post date:** [February 19, 2019, 10:00am UTC](https://discuss.jsonapi.org/t/resource-status/1516/9 "2019-02-19T10:00:10Z")

</div>

What does ALPS stand for?

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [February 19, 2019, 10:13am UTC](https://discuss.jsonapi.org/t/resource-status/1516/10 "2019-02-19T10:13:06Z")

</div>

ALPS = Application-Level Profile Semantics  
[http://alps.io/spec/drafts/draft-01.html](http://alps.io/spec/drafts/draft-01.html)

---

<div class="post-metadata">

**Author:** ![systemovich](https://avatars.discourse-cdn.com/v4/letter/s/b4bc9f/32.png) [@systemovich](https://discuss.jsonapi.org/u/systemovich)\
**Post date:** [February 19, 2019, 10:14am UTC](https://discuss.jsonapi.org/t/resource-status/1516/11 "2019-02-19T10:14:21Z")

</div>

To the links.meta field of a relationship, I added an “allowed” array of HTTP verbs.

```
"relationships": {
    "prices": {
        "links": {
            "href": "https:/example.com/products/product-4/prices",
            "meta": {
                "allowed": ["GET", "PATCH"],
            }
        }
    }
}
```

---

<div class="post-metadata">

**Author:** ![rickardoberg](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/rickardoberg/32/594_2.png) [@rickardoberg](https://discuss.jsonapi.org/u/rickardoberg)\
**Post date:** [February 20, 2019, 2:16am UTC](https://discuss.jsonapi.org/t/resource-status/1516/12 "2019-02-20T02:16:48Z")

</div>

I would suggest using JSON Schema instead of ALPS. We started with ALPS but it gets awkward because it doesn’t have a clean way to express all the nuance of JSON, like types and enums. With JSON Schema all of that comes for free, basically.
