Recipe · Relations

Mock an API with relations (foreign keys that hold)

A fake API is useless if a post's authorId points to a user that doesn't exist. The `ref` field type wires foreign keys to real generated ids, so your nested views and joins behave like the real thing.

Updated June 7, 20264 min

One field type: ref

A ref field takes a target written as resource.field — almost always users.id. At generation time, MockSmith fills it with an id drawn from records that really exist in the target resource.

spec
{  "resources": [    {      "name": "users",      "count": 10,      "fields": [        { "name": "id", "type": "uuid" },        { "name": "name", "type": "fullName" }      ]    },    {      "name": "posts",      "count": 40,      "fields": [        { "name": "id", "type": "uuid" },        { "name": "title", "type": "sentence" },        { "name": "authorId", "type": "ref", "ref": "users.id" }      ]    }  ]}

Every key resolves

Take any authorId from GET /posts and GET /users/:that-id returns a real user. No orphans, because the ref only ever picks from ids that were actually generated.

Chain relations as deep as you need

Relations compose. A comment can point to both a post and a user — two ref fields, two valid foreign keys:

comments
{  "name": "comments",  "count": 120,  "fields": [    { "name": "id", "type": "uuid" },    { "name": "body", "type": "paragraph" },    { "name": "postId", "type": "ref", "ref": "posts.id" },    { "name": "authorId", "type": "ref", "ref": "users.id" }  ]}
  • GET/m/you/blog/users/:idthe author behind a post
  • GET/m/you/blog/posts/:id
  • GET/m/you/blog/commentseach row carries valid postId + authorId

Joining on the client

There is no server-side ?include= — you fetch the related record by its id. Because the key is guaranteed valid, the second call never 404s:

client
const base = "https://mocksmith.lioncore.dev/m/you/blog"; const post = await fetch(`${base}/posts/${id}`).then((r) => r.json());// authorId is a real users id — this always resolvesconst author = await fetch(`${base}/users/${post.authorId}`).then((r) => r.json());

Frequently asked

What can ref point to?

Any resource.field in the same project, where the resource exists. It's validated when you save the spec, so a typo'd target is caught immediately, not at request time.

Can two resources reference each other?

Yes. Point posts.authorId at users.id and add a users.lastPostId ref to posts.id if you need the back-reference — both resolve to real ids.

Do the keys stay valid after I POST a new record?

Generated records keep their valid refs. A record you create yourself carries whatever id you send — so if you POST a post, set its authorId to a real user id to keep the graph consistent.

Stop waiting on the backend.

Forge your own mock API in two minutes. Free, up to two projects, no credit card.

Forge a free mock

Read next