Writable and read-only fields

The Question and Pad models expose more fields than the create and update methods accept. A field that is present when you read a resource is not necessarily a field that you can write.

This page documents which fields are writable so that the gap is explicit. It is especially relevant when syncing resources from source control, where a read field that cannot be written is surprising.

Questions

Writable fields are accepted by coderpad.client.QuestionsNamespace.create() and coderpad.client.QuestionsNamespace.update(). Every other field on Question is populated by the server and returned on read only.

Field

Write support

Notes

title

Create and update

Required on create.

language

Create and update

Required on create.

description

Create and update

contents

Create and update

Cannot be combined with file_contents.

solution

Create and update

file_contents

Create and update

For multi-file questions. Maps to the read-side pad environment files rather than to a single field.

zip_file

Create and update

Upload alternative to file_contents.

directory

Create and update

Package a local directory and upload it through the ZIP importer. Cannot be combined with contents, file_contents, or zip_file.

candidate_instructions

Read only

Write support tracked in issue #196.

test_cases

Read only

test_cases_enabled

Read only

contents_for_test_cases

Read only

take_home

Read only

shared

Read only

is_draft

Read only

custom_files

Read only

id

Read only

Server-assigned.

owner_email

Read only

Server-assigned.

used

Read only

Server-managed usage count.

pad_type

Read only

Server-managed.

author_name

Read only

Server-managed.

organization_name

Read only

Server-managed.

public_take_home_setting_id

Read only

Server-managed.

created_at

Read only

Server-managed timestamp.

updated_at

Read only

Server-managed timestamp.

Directory uploads

Pass directory=Path(...) to create or update a multi-file question from local files. The client builds a ZIP in memory and sends it using the same multipart field as zip_file. It preserves relative paths and file bytes, includes hidden files, and creates no temporary files. The asynchronous client performs file operations and compression in a worker thread.

All files in the supplied directory are uploaded. Symbolic links inside the directory are rejected. An empty directory produces an empty ZIP. Missing directories and paths that are regular files raise NotADirectoryError.

To exclude files or transform their contents, prepare a staging directory before uploading. Use shutil.copytree() with its ignore callback, such as shutil.ignore_patterns(), and tempfile.TemporaryDirectory for cleanup. An already-prepared directory can be uploaded directly without copying.

"""Filter a directory, then upload the staged files."""

from pathlib import Path
from shutil import copytree, ignore_patterns
from tempfile import TemporaryDirectory

from coderpad.client import CoderPad

with TemporaryDirectory() as temporary:
    source = Path(temporary) / "source"
    source.mkdir()
    _ = (source / "main.py").write_text(
        data="print('Hello')\n", encoding="utf-8"
    )
    directory = Path(
        copytree(
            src=source,
            dst=Path(temporary) / "upload",
            ignore=ignore_patterns(
                "node_modules", "__pycache__", "*.pyc", "uv.lock"
            ),
        )
    )
    with CoderPad(api_key="test-key") as client:
        client.questions.update(
            question_id="123",
            directory=directory,
        )

Directory uploads retain the server’s ZIP importer behavior. Live verification found that ZIP uploads generate a missing .cpad file for Python and TypeScript projects, including default run and test targets. Uploading the same files with file_contents does not generate that file. Keep repository-specific exclusions and source transformations in the caller.

Pads

Writable fields are accepted by coderpad.client.PadsNamespace.create() and coderpad.client.PadsNamespace.update(). Every other field on Pad is populated by the server and returned on read only.

Field

Write support

Notes

title

Create and update

language

Create and update

contents

Create and update

notes

Create and update

Private notes for the interviewer.

question_id

Create only

Seeds the pad from an existing question. Not a field on the read model; see question_ids instead.

ended

Update only

Set to True to end the interview. Reflected on read as ended_at.

deleted

Update only

Set to True to delete the pad.

id

Read only

Server-assigned.

state

Read only

Server-managed.

owner_email

Read only

Server-assigned.

private

Read only

Server-managed.

execution_enabled

Read only

Server-managed.

participants

Read only

Server-managed.

events

Read only

Server-managed.

ended_at

Read only

Set by passing ended to update.

url

Read only

Server-assigned.

playback

Read only

Server-assigned.

drawing

Read only

Server-managed.

type

Read only

Server-managed.

question_ids

Read only

Seed questions via question_id on create.

pad_environment_ids

Read only

Server-managed.

active_environment_id

Read only

Server-managed.

team

Read only

Server-managed.

history

Read only

Server-managed.

created_at

Read only

Server-managed timestamp.

updated_at

Read only

Server-managed timestamp.

Candidate instruction steps can carry an optional name alongside their instructions and default_visible values. The clients preserve these names when reading or writing questions. Pass shared=True or shared=False to question creation and updates to set organization sharing explicitly. Only the author can change sharing. Pass custom_database_id to associate a question with a custom database. Omitted values retain the server defaults or existing settings.

Project question starter files

Question.file_contents contains starter overlays. These differ from custom_files, which contains downloadable attachments. Question.question_variants contains lightweight summaries, without code or timestamps. Use the variants endpoint to retrieve full variants.

QuestionFileContent accepts a required path and optional contents, hidden, and deleted flags. A removal entry can contain just its path and deleted=True. Omitted flags stay omitted. Empty contents stay empty.

On creation, structured files overlay template files. An empty overlay uses the unmodified template. ZIP uploads replace template files except the preserved .cpad directory, which cannot be deleted. On parent-question updates, the API ignores deleted entries. This differs from variant updates, where an empty file list restores the template.

Interview analytics

Individual pads can include interview_highlights, interview_outline, transcript, transcript_source_unavailable, and review_reports. These values depend on account features and permissions. Absent values remain None. Empty transcript and review arrays remain empty lists. The outline preserves structured JSON. Transcript timestamps are Unix milliseconds, and review reports include their processing status, file paths, and optional report or error text.

Pad pagination

Pass cursor to pads.list to continue an opaque cursor. When supplied, it takes precedence over page and sort. pads.all follows the cursor or numeric page in each returned next_page link. Links must refer to the configured API origin and pads endpoint. Credentials stay on that origin.

Question filters and sorting

questions.list and questions.all accept text and pad_types. Pad types are any, live, and take_home. Multiple values use repeated pad_types[] query keys. Organization question methods accept pad_type (live or take_home) and language. The server includes questions usable in any pad when applying its usage filters.

QuestionSortOrder supports title, usage count, and creation or update timestamps in either direction. Existing SortOrder timestamp values stay supported. Omitted sorting preserves the API default. Pad and event sorting continues to use SortOrder. Both question enumerators retain filters on every page and follow the returned numeric page link.

Pad access and creation controls

pads.create and pads.update accept private (the waiting room), execution_enabled, user_email (ownership), restrict_interviewer_access, allowed_interviewer_emails, and disable_coaching_tips. Omitted values preserve server defaults, and explicit False values are sent. execution_enabled is sent as the string "true" or "false". The email list replaces existing access: omit it to preserve the list, or pass [] to clear it. Access-list writes use a JSON body through the default transport. Custom transports must support JSON for these requests. Scalar-only mutations continue to use form bodies.

Only creation accepts team_id, take_home, take_home_time_limit (in minutes), and ai_assist_enabled. Omitting the time limit or AI setting inherits the question or organization configuration. Pad.allowed_interviewer_emails retains the returned list, including an empty list, and is None when the API omits that metadata. These fields are available on both synchronous and asynchronous clients.