API Docs

Submissions API

Submissions capture employee story inputs and are linked to both an employee and campaign period.

Endpoints

  • GET /api/v1/submissions
  • POST /api/v1/submissions
  • GET /api/v1/submissions/:id
  • PATCH /api/v1/submissions/:id
  • POST /api/v1/submissions/:id/parse_spin
  • POST /api/v1/submissions/parse_spin_all
  • POST /api/v1/submissions/:id/generate_content
  • POST /api/v1/submissions/:id/generate_content/:content_version_id
  • POST /api/v1/submissions/generate_all
  • GET /api/v1/campaign_periods/:campaign_period_id/submissions
  • POST /api/v1/campaign_periods/:campaign_period_id/submissions
  • GET /api/v1/submissions/:submission_id/content_pieces (nested read, full docs on Content Pieces page)

Filtering, Sorting, Include

  • Filters: id, employee_id, campaign_period_id, status
  • Sort fields: id, status, created_at, updated_at, reviewed_at, published_at
  • Include: employee, campaign_period, content_pieces

GET /api/v1/submissions

curl -X GET "https://cases.shipmentbot.com/api/v1/submissions?filter[status]=submitted&include=content_pieces,employee&sort=-created_at&page[number]=1&page[size]=2" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"
{
  "data": [
    {
      "id": "15",
      "type": "submissions",
      "attributes": {
        "status": "submitted",
        "situation": "The customer had a long procurement cycle.",
        "problem": "No template for stakeholder alignment.",
        "implication": "Launch was delayed by three weeks.",
        "solution": "Built an executive rollout brief and weekly check-ins.",
        "raw_content": null,
        "reviewed_at": null,
        "published_at": null,
        "created_at": "2026-03-03T15:00:00.000Z",
        "updated_at": "2026-03-03T15:00:00.000Z"
      },
      "relationships": {
        "employee": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/submissions/15/relationships/employee",
            "related": "https://cases.shipmentbot.com/api/v1/employees/4"
          },
          "data": { "id": "4", "type": "employees" }
        },
        "campaign_period": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/submissions/15/relationships/campaign_period",
            "related": "https://cases.shipmentbot.com/api/v1/campaign_periods/11"
          },
          "data": { "id": "11", "type": "campaign_periods" }
        },
        "content_pieces": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/submissions/15/relationships/content_pieces",
            "related": "https://cases.shipmentbot.com/api/v1/submissions/15/content_pieces"
          },
          "data": [{ "id": "31", "type": "content_pieces" }]
        }
      },
      "links": {
        "self": "https://cases.shipmentbot.com/api/v1/submissions/15"
      }
    }
  ],
  "included": [
    {
      "id": "31",
      "type": "content_pieces",
      "attributes": {
        "status": "generated",
        "position": 0,
        "body": "Here is a polished LinkedIn draft...",
        "image_url": null,
        "generated_at": "2026-03-03T15:04:33.000Z",
        "approved_at": null,
        "published_at": null,
        "created_at": "2026-03-03T15:04:33.000Z",
        "updated_at": "2026-03-03T15:04:33.000Z"
      },
      "relationships": {
        "submission": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/content_pieces/31/relationships/submission",
            "related": "https://cases.shipmentbot.com/api/v1/submissions/15"
          },
          "data": { "id": "15", "type": "submissions" }
        },
        "content_version": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/content_pieces/31/relationships/content_version",
            "related": "https://cases.shipmentbot.com/api/v1/content_versions/7"
          },
          "data": { "id": "7", "type": "content_versions" }
        }
      },
      "links": {
        "self": "https://cases.shipmentbot.com/api/v1/content_pieces/31"
      }
    }
  ],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions?filter%5Bstatus%5D=submitted&include=content_pieces%2Cemployee&sort=-created_at&page%5Bnumber%5D=1&page%5Bsize%5D=2",
    "first": "https://cases.shipmentbot.com/api/v1/submissions?filter%5Bstatus%5D=submitted&include=content_pieces%2Cemployee&sort=-created_at&page%5Bnumber%5D=1&page%5Bsize%5D=2",
    "last": "https://cases.shipmentbot.com/api/v1/submissions?filter%5Bstatus%5D=submitted&include=content_pieces%2Cemployee&sort=-created_at&page%5Bnumber%5D=2&page%5Bsize%5D=2",
    "next": "https://cases.shipmentbot.com/api/v1/submissions?filter%5Bstatus%5D=submitted&include=content_pieces%2Cemployee&sort=-created_at&page%5Bnumber%5D=2&page%5Bsize%5D=2",
    "prev": null
  },
  "meta": {
    "page": {
      "number": 1,
      "size": 2,
      "total_records": 3,
      "total_pages": 2
    }
  }
}

GET /api/v1/submissions/:id

curl -X GET "https://cases.shipmentbot.com/api/v1/submissions/15?include=employee,campaign_period,content_pieces" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"
{
  "data": {
    "id": "15",
    "type": "submissions",
    "attributes": {
      "status": "submitted",
      "situation": "The customer had a long procurement cycle.",
      "problem": "No template for stakeholder alignment.",
      "implication": "Launch was delayed by three weeks.",
      "solution": "Built an executive rollout brief and weekly check-ins.",
      "raw_content": null,
      "reviewed_at": null,
      "published_at": null,
      "created_at": "2026-03-03T15:00:00.000Z",
      "updated_at": "2026-03-03T15:00:00.000Z"
    },
    "relationships": {
      "employee": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/15/relationships/employee",
          "related": "https://cases.shipmentbot.com/api/v1/employees/4"
        },
        "data": { "id": "4", "type": "employees" }
      },
      "campaign_period": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/15/relationships/campaign_period",
          "related": "https://cases.shipmentbot.com/api/v1/campaign_periods/11"
        },
        "data": { "id": "11", "type": "campaign_periods" }
      },
      "content_pieces": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/15/relationships/content_pieces",
          "related": "https://cases.shipmentbot.com/api/v1/submissions/15/content_pieces"
        },
        "data": [{ "id": "31", "type": "content_pieces" }]
      }
    },
    "links": {
      "self": "https://cases.shipmentbot.com/api/v1/submissions/15"
    }
  },
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/15?include=employee,campaign_period,content_pieces"
  },
  "meta": {}
}

POST /api/v1/submissions

Requires both relationships: employee and campaign_period.

curl -X POST "https://cases.shipmentbot.com/api/v1/submissions" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: csb_live_your_token_here" \
  -d '{
    "data": {
      "type": "submissions",
      "attributes": {
        "status": "submitted",
        "situation": "Enterprise client requested security evidence.",
        "problem": "Our team had no reusable package for legal/procurement.",
        "implication": "Timeline slipped and expansion risk increased.",
        "solution": "Assembled a security packet and standard review process."
      },
      "relationships": {
        "employee": {
          "data": { "type": "employees", "id": "4" }
        },
        "campaign_period": {
          "data": { "type": "campaign_periods", "id": "11" }
        }
      }
    }
  }'
{
  "data": {
    "id": "19",
    "type": "submissions",
    "attributes": {
      "status": "submitted",
      "situation": "Enterprise client requested security evidence.",
      "problem": "Our team had no reusable package for legal/procurement.",
      "implication": "Timeline slipped and expansion risk increased.",
      "solution": "Assembled a security packet and standard review process.",
      "raw_content": null,
      "reviewed_at": null,
      "published_at": null,
      "created_at": "2026-03-05T18:35:00.000Z",
      "updated_at": "2026-03-05T18:35:00.000Z"
    },
    "relationships": {
      "employee": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/employee",
          "related": "https://cases.shipmentbot.com/api/v1/employees/4"
        },
        "data": { "id": "4", "type": "employees" }
      },
      "campaign_period": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/campaign_period",
          "related": "https://cases.shipmentbot.com/api/v1/campaign_periods/11"
        },
        "data": { "id": "11", "type": "campaign_periods" }
      },
      "content_pieces": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/content_pieces",
          "related": "https://cases.shipmentbot.com/api/v1/submissions/19/content_pieces"
        },
        "data": []
      }
    },
    "links": {
      "self": "https://cases.shipmentbot.com/api/v1/submissions/19"
    }
  },
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/19"
  },
  "meta": {}
}

PATCH /api/v1/submissions/:id

curl -X PATCH "https://cases.shipmentbot.com/api/v1/submissions/19" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: csb_live_your_token_here" \
  -d '{
    "data": {
      "type": "submissions",
      "id": "19",
      "attributes": {
        "status": "reviewed",
        "reviewed_at": "2026-03-05T18:42:30Z",
        "raw_content": "Raw transcript from discovery call"
      }
    }
  }'
{
  "data": {
    "id": "19",
    "type": "submissions",
    "attributes": {
      "status": "reviewed",
      "situation": "Enterprise client requested security evidence.",
      "problem": "Our team had no reusable package for legal/procurement.",
      "implication": "Timeline slipped and expansion risk increased.",
      "solution": "Assembled a security packet and standard review process.",
      "raw_content": "Raw transcript from discovery call",
      "reviewed_at": "2026-03-05T18:42:30.000Z",
      "published_at": null,
      "created_at": "2026-03-05T18:35:00.000Z",
      "updated_at": "2026-03-05T18:42:31.000Z"
    },
    "relationships": {
      "employee": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/employee",
          "related": "https://cases.shipmentbot.com/api/v1/employees/4"
        },
        "data": { "id": "4", "type": "employees" }
      },
      "campaign_period": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/campaign_period",
          "related": "https://cases.shipmentbot.com/api/v1/campaign_periods/11"
        },
        "data": { "id": "11", "type": "campaign_periods" }
      },
      "content_pieces": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/content_pieces",
          "related": "https://cases.shipmentbot.com/api/v1/submissions/19/content_pieces"
        },
        "data": []
      }
    },
    "links": {
      "self": "https://cases.shipmentbot.com/api/v1/submissions/19"
    }
  },
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/19"
  },
  "meta": {}
}

POST /api/v1/submissions/:id/parse_spin

Parses raw_content into SPIN fields and returns the updated submission in JSON:API format.

curl -X POST "https://cases.shipmentbot.com/api/v1/submissions/19/parse_spin" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"
{
  "data": {
    "id": "19",
    "type": "submissions",
    "attributes": {
      "status": "reviewed",
      "situation": "Enterprise client requested security evidence.",
      "problem": "No reusable package for legal/procurement review.",
      "implication": "Deal timeline slipped and expansion risk increased.",
      "solution": "Built a reusable security packet and legal checklist.",
      "raw_content": "Raw transcript from discovery call",
      "reviewed_at": "2026-03-05T18:42:30.000Z",
      "published_at": null,
      "created_at": "2026-03-05T18:35:00.000Z",
      "updated_at": "2026-03-05T18:55:03.000Z"
    },
    "relationships": {
      "employee": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/employee",
          "related": "https://cases.shipmentbot.com/api/v1/employees/4"
        },
        "data": { "id": "4", "type": "employees" }
      },
      "campaign_period": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/campaign_period",
          "related": "https://cases.shipmentbot.com/api/v1/campaign_periods/11"
        },
        "data": { "id": "11", "type": "campaign_periods" }
      },
      "content_pieces": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/content_pieces",
          "related": "https://cases.shipmentbot.com/api/v1/submissions/19/content_pieces"
        },
        "data": []
      }
    },
    "links": {
      "self": "https://cases.shipmentbot.com/api/v1/submissions/19"
    }
  },
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/19/parse_spin"
  },
  "meta": {}
}

POST /api/v1/submissions/parse_spin_all

Parses all submissions in the current account where situation is null.

curl -X POST "https://cases.shipmentbot.com/api/v1/submissions/parse_spin_all" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"
{
  "parsed": 3,
  "failed": 1,
  "total": 4,
  "failures": [
    {
      "submission_id": 22,
      "error_class": "SpinParser::ApiError",
      "error": "OpenAI request failed: timeout"
    }
  ]
}

POST /api/v1/submissions/:id/generate_content

Generates content for all active content versions in the submission's campaign. Optionally pass content_version_id as a query param to generate one template only.

curl -X POST "https://cases.shipmentbot.com/api/v1/submissions/19/generate_content" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"
curl -X POST "https://cases.shipmentbot.com/api/v1/submissions/19/generate_content?content_version_id=7" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"
{
  "data": [
    {
      "id": "44",
      "type": "content_pieces",
      "attributes": {
        "status": "generated",
        "position": null,
        "body": "Generated post copy...",
        "image_url": null,
        "generated_at": "2026-03-05T19:10:21.000Z",
        "approved_at": null,
        "published_at": null,
        "created_at": "2026-03-05T19:10:21.000Z",
        "updated_at": "2026-03-05T19:10:21.000Z"
      },
      "relationships": {
        "submission": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/content_pieces/44/relationships/submission",
            "related": "https://cases.shipmentbot.com/api/v1/submissions/19"
          },
          "data": { "id": "19", "type": "submissions" }
        },
        "content_version": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/content_pieces/44/relationships/content_version",
            "related": "https://cases.shipmentbot.com/api/v1/content_versions/7"
          },
          "data": { "id": "7", "type": "content_versions" }
        }
      },
      "links": {
        "self": "https://cases.shipmentbot.com/api/v1/content_pieces/44"
      }
    }
  ],
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/19/generate_content?page%5Bnumber%5D=1&page%5Bsize%5D=25",
    "first": "https://cases.shipmentbot.com/api/v1/submissions/19/generate_content?page%5Bnumber%5D=1&page%5Bsize%5D=25",
    "last": "https://cases.shipmentbot.com/api/v1/submissions/19/generate_content?page%5Bnumber%5D=1&page%5Bsize%5D=25",
    "next": null,
    "prev": null
  },
  "meta": {
    "page": {
      "number": 1,
      "size": 25,
      "total_records": 1,
      "total_pages": 1
    }
  }
}

POST /api/v1/submissions/:id/generate_content/:content_version_id

Shortcut route for generating one content version without query params.

curl -X POST "https://cases.shipmentbot.com/api/v1/submissions/19/generate_content/7" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"

POST /api/v1/submissions/generate_all

For submissions where all SPIN fields are populated, generates any missing pieces for active content versions.

curl -X POST "https://cases.shipmentbot.com/api/v1/submissions/generate_all" \
  -H "Accept: application/json" \
  -H "X-API-Key: csb_live_your_token_here"
{
  "generated": 14,
  "failed": 2,
  "total": 16
}

GET /api/v1/campaign_periods/:campaign_period_id/submissions

curl -X GET "https://cases.shipmentbot.com/api/v1/campaign_periods/11/submissions?sort=-created_at" \
  -H "X-API-Key: csb_live_your_token_here"
{
  "data": [
    {
      "id": "19",
      "type": "submissions",
      "attributes": {
        "status": "reviewed",
        "situation": "Enterprise client requested security evidence.",
        "problem": "Our team had no reusable package for legal/procurement.",
        "implication": "Timeline slipped and expansion risk increased.",
        "solution": "Assembled a security packet and standard review process.",
        "raw_content": "Raw transcript from discovery call",
        "reviewed_at": "2026-03-05T18:42:30.000Z",
        "published_at": null,
        "created_at": "2026-03-05T18:35:00.000Z",
        "updated_at": "2026-03-05T18:42:31.000Z"
      },
      "relationships": {
        "employee": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/employee",
            "related": "https://cases.shipmentbot.com/api/v1/employees/4"
          },
          "data": { "id": "4", "type": "employees" }
        },
        "campaign_period": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/campaign_period",
            "related": "https://cases.shipmentbot.com/api/v1/campaign_periods/11"
          },
          "data": { "id": "11", "type": "campaign_periods" }
        },
        "content_pieces": {
          "links": {
            "self": "https://cases.shipmentbot.com/api/v1/submissions/19/relationships/content_pieces",
            "related": "https://cases.shipmentbot.com/api/v1/submissions/19/content_pieces"
          },
          "data": []
        }
      },
      "links": {
        "self": "https://cases.shipmentbot.com/api/v1/submissions/19"
      }
    }
  ],
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/campaign_periods/11/submissions?page%5Bnumber%5D=1&page%5Bsize%5D=25",
    "first": "https://cases.shipmentbot.com/api/v1/campaign_periods/11/submissions?page%5Bnumber%5D=1&page%5Bsize%5D=25",
    "last": "https://cases.shipmentbot.com/api/v1/campaign_periods/11/submissions?page%5Bnumber%5D=1&page%5Bsize%5D=25",
    "next": null,
    "prev": null
  },
  "meta": {
    "page": {
      "number": 1,
      "size": 25,
      "total_records": 1,
      "total_pages": 1
    }
  }
}

POST /api/v1/campaign_periods/:campaign_period_id/submissions

In nested create, campaign_period can be omitted from relationships because the route provides it.

curl -X POST "https://cases.shipmentbot.com/api/v1/campaign_periods/11/submissions" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: csb_live_your_token_here" \
  -d '{
    "data": {
      "type": "submissions",
      "attributes": {
        "status": "draft",
        "situation": "Customer wanted executive proof points.",
        "problem": "No historical case-study benchmarks.",
        "implication": "Sales cycle extended into next quarter.",
        "solution": "Published a benchmark-backed case narrative."
      },
      "relationships": {
        "employee": {
          "data": { "type": "employees", "id": "5" }
        }
      }
    }
  }'
{
  "data": {
    "id": "20",
    "type": "submissions",
    "attributes": {
      "status": "draft",
      "situation": "Customer wanted executive proof points.",
      "problem": "No historical case-study benchmarks.",
      "implication": "Sales cycle extended into next quarter.",
      "solution": "Published a benchmark-backed case narrative.",
      "raw_content": null,
      "reviewed_at": null,
      "published_at": null,
      "created_at": "2026-03-05T18:44:10.000Z",
      "updated_at": "2026-03-05T18:44:10.000Z"
    },
    "relationships": {
      "employee": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/20/relationships/employee",
          "related": "https://cases.shipmentbot.com/api/v1/employees/5"
        },
        "data": { "id": "5", "type": "employees" }
      },
      "campaign_period": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/20/relationships/campaign_period",
          "related": "https://cases.shipmentbot.com/api/v1/campaign_periods/11"
        },
        "data": { "id": "11", "type": "campaign_periods" }
      },
      "content_pieces": {
        "links": {
          "self": "https://cases.shipmentbot.com/api/v1/submissions/20/relationships/content_pieces",
          "related": "https://cases.shipmentbot.com/api/v1/submissions/20/content_pieces"
        },
        "data": []
      }
    },
    "links": {
      "self": "https://cases.shipmentbot.com/api/v1/submissions/20"
    }
  },
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/20"
  },
  "meta": {}
}

Error Examples

400 Missing Relationships

{
  "data": null,
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions"
  },
  "meta": {},
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "detail": "employee relationship is required"
    }
  ]
}

404 Related Resource Not In Account

{
  "data": null,
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions"
  },
  "meta": {},
  "errors": [
    {
      "status": "404",
      "title": "Not Found",
      "detail": "Related employee or campaign period not found for this account"
    }
  ]
}

422 Validation Error (duplicate employee+campaign_period)

{
  "data": null,
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions"
  },
  "meta": {},
  "errors": [
    {
      "status": "422",
      "title": "Validation Error",
      "detail": "Employee has already been taken",
      "source": {
        "pointer": "/data/attributes/employee"
      }
    }
  ]
}

422 SPIN Parse Error

{
  "data": null,
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/19/parse_spin"
  },
  "meta": {},
  "errors": [
    {
      "status": "422",
      "title": "Unprocessable Entity",
      "detail": "Submission raw_content is blank"
    }
  ]
}

502 SPIN Parse Error (upstream AI failure)

{
  "data": null,
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/19/parse_spin"
  },
  "meta": {},
  "errors": [
    {
      "status": "502",
      "title": "Bad Gateway",
      "detail": "OpenAI request failed: timeout"
    }
  ]
}

503 SPIN Parse Error (configuration)

{
  "data": null,
  "included": [],
  "links": {
    "self": "https://cases.shipmentbot.com/api/v1/submissions/19/parse_spin"
  },
  "meta": {},
  "errors": [
    {
      "status": "503",
      "title": "Service Unavailable",
      "detail": "OPENAI_API_KEY is not configured."
    }
  ]
}