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.
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.
{ "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:
{ "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/:id— the author behind a post
- GET/m/you/blog/posts/:id
- GET/m/you/blog/comments— each 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:
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 mockRead next
Recipe · Pagination
How to mock a paginated REST API (no backend)
Build a fake REST endpoint with real pagination — page, limit, total and totalPages — and wire an infinite scroll against stable data.
4 minRecipe · Testing
Stable, seeded fake data for your tests
Flaky tests often come from random fixtures. Get deterministic, seeded mock data that's identical on every run — and reset it on a schedule.
4 min