---
title: "Create a service listing"
method: POST
path: "/services"
tags: ["Services"]
---

# Create a service listing

`POST /services`

## Request

- Base URL: `https://api.purplegrain.com/api/v1`
- URL: `https://api.purplegrain.com/api/v1/services`
- Auth: HTTP bearer

Creates a service listing. Requires a name, an owner (a user, or a
business the caller can edit), a place, and a three-letter currency
code. `radius`, when sent, is an integer number of metres from 10000
to 2000000. The slug follows the name.

## Query parameters

- `include` string

## Request body

- ServiceCreateModelAttributes: Flat attributes-adapter request body (Content-Type application/json). Attribute fields and relationships live directly under `data` (no nested `attributes` / `relationships` envelopes). Each relationship is a resource identifier object ({ id, type }). Equivalent JSON:API (nested) shape: `ServiceCreateModel` sent as application/vnd.api+json.
  - `data` object, required
    - `name` string, required
    - `slug` string, nullable
    - `description` string, nullable
    - `status` 'active' | 'inactive', nullable
    - `cost` string, nullable
    - `currency` string, nullable, required
    - `radius` integer, nullable
    - `tags` string[], nullable: Hashtag-style labels (they work like Twitter hashtags) — free-form lowercase tokens stored without a leading hash, e.g. ["slashing", "north-paddock"]. Reusing a tag groups records together, and the /tasks/search and /services/search term parameter matches tags case-insensitively, so a tag aggregates everything labelled with it. Send an empty array to clear every tag (null is accepted and stored as an empty array).
    - `owner` object, nullable
      - `id` string, nullable
      - `type` 'user' | 'organization', nullable
    - `place` object, nullable
      - `id` string, nullable
      - `type` 'city' | 'address', nullable
    - `category` object, nullable
      - `id` string, nullable
      - `type` string, nullable

## Response `200`

Success. When the `include` query parameter is used, the response may contain an `included` array (JSON:API) or inlined related resources (application/json).

- ServicesShowResponseAttributes
  - `data` ServiceModelAttributes: Service in attributes-adapter shape (Accept application/json); fields at top level.
    - `id` string
    - `type` string
    - `slug` string
    - `name` string
    - `status` 'active' | 'inactive'
    - `cost` string, nullable
    - `currency` string, nullable
    - `description` string, nullable
    - `tags` string[]: Hashtag-style labels (they work like Twitter hashtags) — free-form lowercase tokens stored without a leading hash, e.g. ["slashing", "north-paddock"]. Reusing a tag groups records together, and the /tasks/search and /services/search term parameter matches tags case-insensitively, so a tag aggregates everything labelled with it. Always an array — the API never returns null.
    - `radius` integer, nullable
    - `url` string
    - `image_url` string, nullable
    - `image_thumb_url` string, nullable
    - `updated_at` string, date-time
    - `created_at` string, date-time
    - `city` object: Inlined when include=city
    - `place` object: Inlined when include=place
    - `owner` object: Inlined when include=owner
    - `category` object: Inlined when include=category
    - `location` object: Inlined when include=location

## Other responses

- `422`: Invalid request

---

[API](https://skmtc.dev/purplegrain/apis/purple-grain-api.md) · [All operations](https://skmtc.dev/purplegrain/apis/purple-grain-api/llms.txt) · [OpenAPI document](https://skmtc.dev/purplegrain/apis/purple-grain-api/revisions/4bedbc1c784c?raw)
