QA Steps sandbox · Protocol sandbox

GraphQL schema

The Registry of the Duat is a GraphQL API: read the twenty souls of the gods without signing in, then register as a scribe and create, change and banish souls of your own. Everything you write is yours alone.

The schema in SDL

Download schema.graphql
"""
A moment in time: an RFC 3339 date-time string in UTC, e.g. 2025-01-01T09:00:00.000Z.
"""
scalar DateTime

"""Where a soul is in its judgement."""
enum SoulStatus {
  """Arrived in the Duat, not judged yet."""
  WAITING

  """Weighed against the feather of Maat and judged."""
  JUDGED

  """Sent away from the Hall of Maat."""
  BANISHED
}

"""
A soul written in the Registry of the Duat. Souls 1–20 belong to the gods; the souls you create are yours alone.
"""
type Soul {
  """The soul's id. Souls 1–20 are shared and read-only."""
  id: ID!

  """The soul's name. Never null."""
  name: String!

  """Deeds the soul did in life, oldest first."""
  deeds: [String]

  """Weight of the heart on the scales, or null when it was not weighed."""
  weight: Int

  """Whether the soul has been judged."""
  isJudged: Boolean

  """Where the soul is in its judgement."""
  status: SoulStatus

  """A free note about the soul, or null."""
  description: String

  """
  Moment of arrival, RFC 3339 date-time in UTC, e.g. 2025-01-01T09:00:00.000Z
  """
  arrivedAt: DateTime
}

"""
A soul to create or change. updateSoul changes only the fields you send; name is always required.
"""
input SoulInput {
  """The soul's name, 2–40 characters."""
  name: String!

  """Deeds, up to 10, each 1–80 characters."""
  deeds: [String]

  """Weight of the heart, 0–1000."""
  weight: Int

  """A free note, up to 200 characters."""
  description: String

  """Where the soul is in its judgement. WAITING when not sent."""
  status: SoulStatus

  """Moment of arrival. The server's time when not sent."""
  arrivedAt: DateTime
}

"""What loginScribe returns."""
type AuthPayload {
  """
  A scribe token for 60 minutes: send it as Authorization: Bearer <token>.
  """
  token: String!

  """A greeting."""
  message: String
}

"""Reads. No token needed."""
type Query {
  """
  One soul by id. A soul that does not exist, or is another scribe's, answers "Soul not found."
  """
  getSoul(id: ID!): Soul

  """
  One soul by id, at most 2 fields per call (aliases and __typename count).
  """
  getSoulLimited(id: ID!): Soul

  """Souls, newest id first: 10 when limit is not sent."""
  allSouls(limit: Int): [Soul]

  """Your username, or "Anonymous scribe" without a token."""
  currentScribe: String
}

"""
Changes. Every mutation except registerScribe and loginScribe needs a token.
"""
type Mutation {
  """
  Create a scribe account: username 3–15 letters, digits or _, password 8–72 characters.
  """
  registerScribe(username: String!, password: String!): String

  """Sign in: a token for 60 minutes."""
  loginScribe(username: String!, password: String!): AuthPayload

  """Write a new soul of yours."""
  createSoul(input: SoulInput!): Soul

  """Change one of your souls: only the fields you send change."""
  updateSoul(id: ID!, input: SoulInput!): Soul

  """Add one deed to the end of a soul's deeds."""
  patchSoulDeeds(id: ID!, deed: String!): Soul

  """Delete one of your souls for good."""
  banishSoul(id: ID!): String
}

"""Events over WebSocket on the same path."""
type Subscription {
  """Each soul you create, as it is created."""
  soulCreated: Soul
}