# Gridfox Public API skill Use this skill when you need to work with a Gridfox project through its Public API, especially when the goal is to create strong sample data across multiple related tables. The primary use case for this skill is: - inspect the project structure - understand tables, fields, and relationships - generate realistic sample data - create records in a sensible order - link related records correctly This skill is optimized for seeding a project with believable, useful demo data rather than just filling every field with placeholders. --- ## What this API is for This API lets you: - inspect project tables and fields - search records in a table - create records - update records - delete records - upload and download files - inspect audit history - inspect groups and permissions - add and manage users For sample data generation, the most important endpoints are: - `GET /tables` - `POST /data/{tableName}` - `GET /data/{tableName}` - `GET /data/{tableName}/{referenceFieldValue}` --- ## Authentication Use the API key in the `gridfox-api-key` header. Example: ```http gridfox-api-key: prefix.key ```` This API uses an `apiKey` security scheme in the header. --- ## Main objective When asked to add sample data to a Gridfox project: 1. Call `GET /tables` first. 2. Inspect the full structure of every table. 3. Infer how tables relate to each other. 4. Design a coherent sample dataset across the whole project. 5. Create records with `POST /data/{tableName}` in dependency order. 6. Reuse created reference values so relationships are valid and sensible. 7. Prefer quality, realism, and consistency over volume. Do not start posting records before inspecting `GET /tables`. --- ## Required first step: inspect the project schema Always begin with: ```http GET /tables ``` This returns the project tables and their fields. Each table includes: * `name` * `singularName` * `referenceFieldName` * `fields[]` Each field includes: * `name` * `type` * `isRequired` * `isUnique` * `properties` Use this response as the source of truth for what data can be created. --- ## Field types you should expect The schema includes these public field types: * `text` * `textArea` * `richText` * `url` * `number` * `money` * `date` * `time` * `dateTime` * `checkbox` * `file` * `list` * `child` * `parent` * `manyToMany` * `autoCounter` * `image` * `icon` * `formula` * `user` * `percentage` * `multiSelectList` * `multiSelectUser` * `duration` * `email` Treat the field type as the strongest signal for how to populate the field. --- ## Important mindset for sample data The goal is not random fake data. The goal is a project that feels immediately usable when a human opens it. That means sample data should be: * realistic * internally consistent * domain-appropriate * varied * relationship-aware * useful for filtering, sorting, grouping, and reporting Good sample data should make the project feel alive. --- ## High-level workflow ### 1. Discover the schema Call: ```http GET /tables ``` Then build an internal model of: * all tables * each table’s reference field * required fields * unique fields * list options * relationship fields * tables that appear to depend on other tables ### 2. Infer dependencies Look for fields with type: * `parent` * `child` * `manyToMany` Also inspect relationship-related properties such as: * `relatedTableName` Use these to determine creation order. Typical rule: * create lookup/master tables first * create primary business entities second * create dependent or transactional records after that * create junction-style links only after the referenced records exist ### 3. Design the sample dataset Before creating anything, sketch a coherent dataset. Examples: * CRM: companies, contacts, deals, activities * Projects: clients, projects, tasks, issues, files * HR: departments, employees, leave requests, reviews * Inventory: suppliers, products, purchase orders, stock movements * Operations: sites, assets, maintenance jobs, inspections The data should tell a believable story. ### 4. Create records in dependency order Use: ```http POST /data/{tableName} ``` Create parent records first. Save the returned `referenceFieldValue` for each record. Reuse those references when creating related records. ### 5. Verify and enrich Use: ```http GET /data/{tableName} GET /data/{tableName}/{referenceFieldValue} ``` to verify records exist and relationships look correct. If needed, enrich or fix records with: ```http PUT /data/{tableName}/{referenceFieldValue} ``` --- ## How to infer relationships When reading `GET /tables`, inspect all fields for relationship patterns. ### Parent / child A field of type `parent` or `child` usually signals one-to-many structure. Examples: * Tasks belong to a Project * Contacts belong to a Company * Line Items belong to an Order Usually: * create the parent table records first * then create child records referencing those parents ### Many-to-many A field of type `manyToMany` suggests records can link to many records in another table. Examples: * Projects ↔ People * Products ↔ Tags * Contacts ↔ Campaigns Make sure enough records exist on both sides before populating these links. ### Related table metadata If `properties` includes a `relatedTableName`, use it to map dependencies explicitly. ### Name-based hints If metadata is thin, field names may help: * `Company` * `Client` * `Project` * `Assignee` * `Manager` * `Department` * `Supplier` * `Category` * `Parent Task` Use this only after checking actual type and properties. --- ## Creation order strategy Always create data in an order that satisfies dependencies. A good general order is: 1. static lookup tables 2. top-level entities 3. child entities 4. many-to-many links 5. optional enrichment fields such as files or notes ### Static lookup tables These often include tables such as: * Departments * Categories * Status Sets * Regions * Suppliers * Teams They provide values other tables reference. ### Top-level entities These are core records that other records hang off. Examples: * Companies * Clients * Projects * Employees * Products * Sites ### Child entities Examples: * Contacts under Companies * Tasks under Projects * Order Lines under Orders * Maintenance Logs under Assets ### Many-to-many links Populate these only after enough records exist on each side. --- ## Record count guidance Prefer moderate, rich datasets over huge shallow ones. A strong default seed might be: * 3 to 8 records for lookup/master tables * 10 to 30 records for core business tables * 20 to 80 records for child/transaction tables Adjust to the schema size. Examples: * small simple project: 5 to 20 total records * medium business workflow: 30 to 120 total records * richer demo environment: 100+ records, but only if relationships stay coherent Avoid creating so much data that the project becomes noisy or hard to understand. --- ## How to generate high-quality sample data ### Use a consistent domain story Do not generate isolated nonsense. Pick a scenario that fits the table names. Examples: * software agency managing client projects * manufacturing team tracking suppliers and orders * nonprofit managing volunteers and events * facilities team tracking sites, assets, and inspections Then keep names, dates, and relationships aligned with that scenario. ### Make values realistic Prefer: * believable company names * plausible personal names * sensible dates * meaningful descriptions * varied statuses * realistic amounts and percentages Avoid: * `Test 1`, `Test 2`, `ABC`, `Lorem Ipsum` * every date being today * every checkbox being false * every money value being rounded and identical ### Add variety Make sure the sample data supports common UI workflows: * filtering by status * sorting by date * grouping by owner * seeing overdue vs upcoming items * comparing small vs large values ### Keep cross-table consistency Examples: * a task’s due date should usually fall inside or near its project timeline * a contact should belong to a company that exists * an invoice total should feel consistent with line items * an employee should belong to a valid department * a maintenance log should reference a real asset and site --- ## Field-by-field seeding guidance Use the field type and field name together. ### `text` Populate with short natural values. Examples: * names * titles * codes * short labels ### `textArea` Use 1 to 3 sentence descriptions, notes, summaries, or comments. ### `richText` Use simple rich content style text that would look reasonable in a UI. Do not over-format. ### `url` Use realistic URLs matching the scenario. Examples: * company websites * documentation links * ticket links ### `number` Use plausible integer or decimal values. Vary them. ### `money` Use realistic amounts. Respect currency where provided. ### `date` Use dates distributed around a believable timeline. Examples: * some in the past * some current * some upcoming ### `time` Use practical working-day times unless the domain suggests otherwise. ### `dateTime` Use believable timestamps, especially for events, deadlines, or logs. ### `checkbox` Mix true and false meaningfully. ### `list` Only use values from the configured list items. Inspect `properties.items`. ### `multiSelectList` Use one or more configured list options. Vary the combinations. ### `email` Use realistic email formats. ### `user` Use only if appropriate and only with valid project users if required by the API or schema behavior. ### `multiSelectUser` Same principle as `user`, but possibly multiple users. ### `percentage` Use values that make business sense, not random decimals everywhere. ### `duration` Use meaningful durations in the likely unit or format expected by the project. ### `file` Usually skip initially unless the task explicitly asks for file sample data. If needed, create the record first, then upload files using the file endpoint. ### `image` Usually skip unless asked or unless sample visuals add clear value. ### `formula` Do not try to populate directly unless the schema clearly allows it. Usually derived. ### `autoCounter` Do not try to fabricate this manually unless required by the system behavior. ### `parent`, `child`, `manyToMany` Populate only after creating related records and only with valid references. --- ## Handling required and unique fields ### Required fields Always identify fields where: * `isRequired = true` Every created record should satisfy required fields. If a required field is ambiguous, infer a sensible value from table context. ### Unique fields Always identify fields where: * `isUnique = true` Examples: * codes * emails * order numbers * project keys * SKUs * reference names Do not reuse values across records for unique fields. Generate values systematically, for example: * `PRJ-001` * `PRJ-002` * `SKU-1001` * `INV-2026-001` --- ## Using the reference field correctly Each table has a `referenceFieldName`. This is especially important because: * records are retrieved by `referenceFieldValue` * created resources return `referenceFieldValue` After creating a record with: ```http POST /data/{tableName} ``` the API returns: ```json { "referenceFieldValue": "..." } ``` Store this value immediately. Use it to: * fetch the record later * update it later * map relationships from other tables Maintain an internal lookup like: * table name * human label * created reference value Example: * Companies → Acme Industrial → `COMP-001` * Projects → Warehouse Upgrade → `PROJ-004` * Employees → Maya Chen → `EMP-012` --- ## Creating records Use: ```http POST /data/{tableName} Content-Type: application/json ``` with a request body that matches the table’s fields. You may also use these query parameters if needed: * `dataProperty` * `ignoreProperties` Usually, for straightforward record creation, send a direct JSON object unless there is a specific integration reason to wrap or ignore properties. ### Example pattern ```http POST /data/Projects ``` ```json { "Name": "Warehouse Upgrade Phase 1", "Client": "Acme Distribution", "Status": "In Progress", "StartDate": "2026-03-01", "EndDate": "2026-06-30", "Budget": 125000 } ``` The exact field names and relationship payload shapes depend on the actual table schema. Always align with the table definitions returned by `GET /tables`. --- ## Sensible relation strategy The key requirement is not just creating records, but creating sensible relations. ### Principles * every child should belong to a plausible parent * distributions should be uneven, like real life * not every entity should link to every other entity * some parents should have many children, some few * statuses and dates should support the relationship ### Good examples * one client has 3 projects, another has 1 * one project has 12 tasks, another has 4 * some contacts are primary decision makers, others are operational * some orders have 1 line, others have 5 * some employees manage others ### Weak examples * every company has exactly 2 contacts * every project has exactly 5 tasks * every status is equally represented * every date is sequential without meaning --- ## Suggested algorithm for sample data generation ### Step 1: inspect all tables Call `GET /tables`. ### Step 2: classify tables For each table, classify it roughly as: * lookup table * core/master table * child/transaction table * junction/relationship-heavy table ### Step 3: build dependency graph Use relationship fields and related table metadata. ### Step 4: choose a scenario Infer from table names. Examples: * `Companies`, `Contacts`, `Deals` → CRM * `Projects`, `Tasks`, `Clients` → project delivery * `Products`, `Suppliers`, `Orders` → inventory/procurement * `Employees`, `Departments`, `Leave Requests` → HR ### Step 5: generate a seed plan For each table decide: * how many records to create * what variation to include * which previously created records each one should reference ### Step 6: create in order Post records table by table. ### Step 7: track created references Save every returned `referenceFieldValue`. ### Step 8: backfill optional relationships if needed If some many-to-many or secondary references are easier after initial creation, use `PUT` later. --- ## Using search and read endpoints during seeding ### Search records Use: ```http GET /data/{tableName} ``` This is useful to: * check whether sample data already exists * avoid duplicate seeding * inspect current records * paginate results * sort results * filter results Relevant query parameters include: * `OrderByInternal` * `$filter` * `ExtraParameters` * `OrderBy` * `Descending` * `Paged` * `PageNumber` * `PageSize` ### Read a specific record Use: ```http GET /data/{tableName}/{referenceFieldValue} ``` This is useful to verify a created record or inspect its structure after creation. --- ## Updating records after creation Use: ```http PUT /data/{tableName}/{referenceFieldValue} ``` This is useful when: * you needed to create parent records first * you want to enrich records after related references exist * you want to add optional fields later * you need to repair a partially valid seed Query parameters include: * `dataProperty` * `ignoreProperties` --- ## File seeding For file fields, the flow is different. ### Add files to a record field ```http POST /data/{tableName}/{referenceFieldValue}/{fieldName} Content-Type: multipart/form-data ``` Body uses: * `Files[]` ### Download file ```http GET /data/{tableName}/{referenceFieldValue}/{fieldName}/{fileName} ``` ### Delete file ```http DELETE /data/{tableName}/{referenceFieldValue}/{fieldName}/{fileName} ``` For most sample data tasks, files are optional. Use them only when they materially improve the demo, such as: * contracts * invoices * photos * reports * inspection attachments --- ## Audit endpoint Use: ```http GET /data/{tableName}/{referenceFieldValue}/audit ``` This returns audit history for a specific record. This is usually not required for initial sample data seeding, but can help validate that records were created or updated as expected. --- ## Permissions and safety checks Before doing large write operations, it may be useful to inspect: ```http GET /permissions ``` This returns project-level and entity-level permissions. Use this when: * writes fail unexpectedly * you need to understand access restrictions * some tables appear readable but not writable --- ## Users and groups These endpoints exist but are secondary for sample data seeding: * `GET /groups` * `POST /users` * `PUT /users/{userId}` * `DELETE /users/{userId}` Only use them when the task explicitly includes user/group setup. Do not assume you should modify users just because user-type fields exist in tables. --- ## Practical seeding heuristics by common schema pattern ## CRM-style schema Tables might include: * Companies * Contacts * Deals * Activities Suggested approach: * create 8 to 15 companies * create 1 to 4 contacts per company * create deals for some, not all, companies * vary deal stage and amount * create activities linked to deals or contacts Use industries, company sizes, and realistic contact roles. ## Project management schema Tables might include: * Clients * Projects * Tasks * Milestones * Issues Suggested approach: * create a few clients * create several active and completed projects * create tasks with mixed statuses and owners * add milestones and issues to only some projects * keep task dates aligned to project dates ## Inventory schema Tables might include: * Suppliers * Categories * Products * Purchase Orders * Stock Movements Suggested approach: * create a handful of suppliers and categories * create products distributed across categories * create purchase orders with realistic timing * create stock movement history for some products ## HR schema Tables might include: * Departments * Employees * Managers * Leave Requests * Reviews Suggested approach: * create departments first * create employees with department membership * create manager relationships * create leave requests with varied statuses * create reviews for a subset of employees --- ## Quality bar The seeded project should satisfy all of the following: * required fields are populated * unique fields are truly unique * relation fields point to valid related records * list fields only use allowed values * data fits the domain implied by the schema * records vary enough to be useful in the UI * the dataset feels coherent, not random A human opening the project should quickly understand what the system is for. --- ## Error handling ### 400 Bad Request Usually means: * missing required fields * invalid field names * invalid field values * malformed payload * unsupported relationship payload shape Response may contain: ```json { "messages": ["..."] } ``` Read and adapt. ### 401 Unauthorized Check the `gridfox-api-key` header. ### 403 Forbidden You may have read access but not write access for that table or project. ### 404 Not Found Usually means the table name, record reference, or endpoint path is wrong. --- ## Good operational behavior ### Do * inspect tables first * plan creation order before posting * keep a map of created references * generate coherent data * verify created records when needed * use moderate record counts * prefer realistic relationships ### Do not * blindly post random placeholder records * assume field names without reading `/tables` * create child records before parents * ignore required or unique constraints * force formula or computed fields without evidence * flood the project with junk data --- ## Minimal recommended execution pattern 1. `GET /tables` 2. Analyze fields, required constraints, uniqueness, and relationships 3. Build a dependency-aware seeding plan 4. `POST /data/{tableName}` for parent tables 5. Save returned `referenceFieldValue`s 6. `POST /data/{tableName}` for dependent tables using those references 7. `PUT /data/{tableName}/{referenceFieldValue}` for optional backfills if needed 8. `GET /data/{tableName}` or `GET /data/{tableName}/{referenceFieldValue}` to verify --- ## Practical notes from live API use These notes come from actually seeding a Gridfox project through the public API. ### Confirmed base URL Use: ```http https://api.gridfox.com ``` Example: ```http GET https://api.gridfox.com/tables ``` ### Swagger is available The public OpenAPI document is available at: ```http GET https://api.gridfox.com/swagger/v1/swagger.json ``` Use this when request behavior is unclear. ### `GET /data/{tableName}` response shape In practice, list endpoints return an envelope like: ```json { "records": [], "pageNumber": 1, "pageSize": 50, "totalRecords": 0, "totalPages": 0 } ``` Do not assume the response is a raw array. For counts, prefer: * `totalRecords` for the total in the table * `records.length` for the current page size ### Field names in record payloads are normalized When reading records back, Gridfox often returns keys with lower-cased initial characters such as: * `action ID` * `action Title` * `start Date` * `due Date` Do not assume the response keys match the exact write casing from the schema. Always map record fields defensively when reading responses. ### Parent field writes For `POST`, parent fields can be written successfully using the related record's reference value directly. Examples that worked in live use: ```json { "Organisation": 1 } ``` and ```json { "Organisation": "1" } ``` A nested object payload was not reliable. Prefer sending the direct reference value unless testing proves the project requires another shape. ### `PUT` requires the reference field in both places When updating an existing record, include the reference value: * in the URL * in the JSON payload Example: ```http PUT /data/Actions/1 ``` ```json { "Action ID": 1, "Action Title": "Complete usability trace matrix remediation and approval", "Product": 1, "Gap": 1, "Status": "In Progress", "Start Date": "2026-03-18T09:00:00Z", "Due Date": "2026-04-24T17:00:00Z" } ``` If the payload omits the reference field, updates may fail. If the payload includes a conflicting identifier shape, the API may return: ```json { "messages": [ "Conflicting values found for parameter 'id'" ] } ``` ### Date and datetime fields `dateTime` fields accepted ISO 8601 UTC timestamps in live use. Example: ```json { "Start Date": "2026-03-18T09:00:00Z" } ``` Use full timestamps for `dateTime` fields rather than plain dates unless testing shows plain dates are accepted. ### Re-fetch schema if the project is being edited The live project schema changed during the session. New fields appeared later on the `Actions` table: * `Start Date` * `Due Date` Do not assume the schema is static across a long run. If a user may be editing the project structure while seeding, call `GET /tables` again before a major write phase. ### Verification caveats A few practical verification rules were useful: * formula and summary fields may take a short time to reflect newly created child records * list endpoints may show child fields as empty strings rather than expanded child data * parent links are often returned as the related record reference value, not a nested object When verifying relationships, prefer checking the actual child tables directly instead of relying on child summary fields in parent list responses. ### Reference values after deletes Auto-counter reference values continue increasing after deletes. Do not expect deleted IDs to be reused. This matters if you: * seed test records first * delete them * then create the final dataset Always capture the returned `referenceFieldValue` from the actual create response instead of assuming sequential IDs. ### Recommended live-use workflow For real seeding work, the most reliable pattern was: 1. `GET /tables` 2. inspect Swagger if payload shape is unclear 3. create 1 small probe record if needed 4. verify how reads and references come back 5. seed the full dataset in dependency order 6. pause briefly before verifying formula-heavy summaries 7. use `PUT` only with the reference ID present in both URL and payload --- ## Example agent objective statement When asked to populate a Gridfox project with sample data, always begin by calling `GET /tables`, infer the schema and table relationships, then create realistic records with `POST /data/{tableName}` in dependency order, saving returned `referenceFieldValue`s so related records can reference each other sensibly across the project. --- ## Summary This skill is about structured, high-quality project seeding. The essential rule is: * inspect first with `/tables` * create records second with `/data/{tableName}` * build believable relations across tables * optimize for realism and usefulness Always prefer a smaller, coherent dataset over a large, low-quality one.