> ## Documentation Index > Fetch the complete documentation index at: https://docs.lobstersoftware.com/llms.txt > Use this file to discover all available pages before exploring further. # Create profile group > Creates a group in the group `parentId`, or on the top level without one, and returns it with its server-assigned `id`. The caller needs the group right on the parent, as in the Lobster UI (403); the name is unique among the groups of the parent (409); a blank name or an unknown parent answers 422. A group created below another one is granted to the roles that hold that group, with the same rights, as the UI does. ## OpenAPI ````json POST /platform/api/profiles/preview/groups { "openapi": "3.1.0", "info": { "title": "Lobster Platform API", "description": "**PREVIEW:** This API is in preview and under active development. Endpoints and schemas are subject to breaking changes, and backward compatibility is not guaranteed until the API is promoted to a stable version.\n\nREST API of the Lobster Platform for headless clients. Every operation, schema and member of this document carries a description, and the create operations carry complete examples. Each tag links the page of the Lobster documentation that explains its resources.\n\n## Authentication\nFour authentication flows are available. All of them produce a bearer token that must be sent as `Authorization: Bearer ` on every request.\n\n1. **Authorization code with PKCE** (acting as a user; works with Microsoft and other SSO): the steps are in the `OAuth2AuthorizationCode` security scheme.\n2. **OAuth2 Client Credentials** (machine-to-machine): exchange a client id/secret provisioned in the Lobster administration UI at `POST /dw/register/oauth/token` with `grant_type=client_credentials&client_id=&client_secret=`.\n3. **UI Session Bearer Token**: log in via the Lobster web UI, then exchange the session cookie for a token at `GET /auth/sessionBearerToken`.\n4. **Guest User Login Token**: append a GuestUser `loginToken` as a URL query parameter (`?loginToken=`) to establish a session without a password, then retrieve the bearer token the same way.", "version": "preview" }, "servers": [ { "url": "https://platform-beta-test.lobster-cloud.com" } ], "security": [ { "OAuth2": [] }, { "OAuth2AuthorizationCode": [] }, { "SessionBearer": [] } ], "tags": [ { "name": "Channels", "description": "The channels of a partner, the concrete connections a profile uses to receive or send.", "externalDocs": { "description": "Lobster documentation", "url": "https://docs.lobstersoftware.com/docs/en/manage-partners-channels" } }, { "name": "Functions", "description": "The catalogue of mapping functions a profile's mapping can call.", "externalDocs": { "description": "Lobster documentation", "url": "https://docs.lobstersoftware.com/docs/en/functions" } }, { "name": "Partners", "description": "Integration partners, the business parties profiles exchange data with.", "externalDocs": { "description": "Lobster documentation", "url": "https://docs.lobstersoftware.com/docs/en/manage-partners" } }, { "name": "Profiles", "description": "Integration profiles: what data comes in, how it is mapped and where the result goes.", "externalDocs": { "description": "Lobster documentation", "url": "https://docs.lobstersoftware.com/docs/en/profiles" } } ], "externalDocs": { "description": "Lobster documentation", "url": "https://docs.lobstersoftware.com/docs/en/profiles" }, "paths": { "/platform/api/profiles/preview/groups": { "post": { "tags": [ "Profiles" ], "summary": "Create profile group", "description": "Creates a group in the group `parentId`, or on the top level without one, and returns it with its server-assigned `id`. The caller needs the group right on the parent, as in the Lobster UI (403); the name is unique among the groups of the parent (409); a blank name or an unknown parent answers 422. A group created below another one is granted to the roles that hold that group, with the same rights, as the UI does.", "operationId": "createGroup", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/core.ProfileGroup", "title": "ProfileGroup" }, "examples": { "group": { "summary": "Create a group", "description": "A group in the group `parentId`; leave `parentId` out for the top level.", "value": { "class": "core.ProfileGroup", "name": "Archive", "parentId": "6bb76781_199702d94be_2714_9a14992bf4897187_6bb76781_1996f5f9530_-8000" } } } } } }, "responses": { "201": { "description": "Group created.", "headers": { "Location": { "description": "URI of the created group.", "style": "simple", "schema": { "format": "uri" } } }, "content": { "application/json": { "schema": { "type": "object", "description": "Standard Platform API success envelope. Every response carries exactly one of `data` (success) or `error` (failure) at top level.", "properties": { "data": { "$ref": "#/components/schemas/core.ProfileGroup", "title": "ProfileGroup" } }, "required": [ "data" ] } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/UnprocessableEntity" }, "500": { "$ref": "#/components/responses/ServerError" } } } } }, "components": { "schemas": { "core.ProfileGroup": { "type": "object", "description": "A profile group, a node of the profile tree. A profile's `group` holds its `id`.", "properties": { "class": { "type": "string", "const": "core.ProfileGroup", "description": "The type of this object, always `core.ProfileGroup`. Required where the member it is sent in accepts several types." }, "groups": { "type": "array", "description": "The groups directly in this group, by name. Present on a single-group response only; a sent value is ignored.", "items": { "$ref": "#/components/schemas/core.ProfileTreeRef", "title": "ProfileTreeRef" }, "readOnly": true }, "id": { "type": "string", "description": "The group's identifier: the value a profile's `group` holds and the path parameter of `GET /groups/{id}`; `root` for the top level. Assigned by the server; a sent value is ignored.", "readOnly": true }, "name": { "type": "string", "description": "The name the Lobster UI shows for the group; unique among the groups of one parent.", "examples": [ "Orders" ] }, "parentId": { "type": "string", "description": "The `id` of the group this group sits in; absent for a group on the top level. On create, the group to create it in. Send `null` in a patch to move the group to the top level." }, "profiles": { "type": "array", "description": "The profiles directly in this group the caller may view, by name. Present on a single-group response only; a sent value is ignored.", "items": { "$ref": "#/components/schemas/core.ProfileTreeRef", "title": "ProfileTreeRef" }, "readOnly": true } }, "title": "ProfileGroup" }, "core.ProfileTreeRef": { "type": "object", "description": "A reference to a subgroup or a profile of a group: its id, name and the path to fetch it.", "properties": { "class": { "type": "string", "const": "core.ProfileTreeRef", "description": "The type of this object, always `core.ProfileTreeRef`. Required where the member it is sent in accepts several types." }, "href": { "type": "string", "description": "The server-relative path that returns the referenced group or profile." }, "id": { "type": "string", "description": "The identifier of the referenced group or profile." }, "name": { "type": "string", "description": "The name of the referenced group or profile.", "examples": [ "acme-order-import" ] } }, "title": "ProfileTreeRef" }, "ErrorResponse": { "type": "object", "description": "Standard Platform API error envelope: every failed request carries a single `error` object. Every response carries exactly one of `data` (success) or `error` (failure) at top level.", "properties": { "error": { "$ref": "#/components/schemas/Error", "description": "What went wrong: branch on its `code`, show its `message`, and read `details` for one entry per failed member." } }, "required": [ "error" ] }, "Error": { "type": "object", "description": "The error that made the request fail.", "properties": { "code": { "type": "string", "description": "Stable machine-readable `UPPER_SNAKE` error code for programmatic handling, e.g. `PARTNER_NOT_FOUND`, `VALIDATION_FAILED` or `FORBIDDEN`. New codes may be added over time; treat an unknown code according to the HTTP status class. The HTTP status itself is carried by the status line only, never duplicated here." }, "message": { "type": "string", "description": "Human-readable, non-localized explanation. Branch on `code`, never on this text." }, "details": { "type": "array", "description": "Individual failures within the request, e.g. one entry per violated field.", "items": { "$ref": "#/components/schemas/ErrorDetail" } } }, "required": [ "code", "message" ] }, "ErrorDetail": { "type": "object", "description": "A single failure within the request.", "properties": { "code": { "type": "string", "description": "Stable machine-readable `UPPER_SNAKE` code of this individual failure, e.g. `FIELD_REQUIRED`, `FIELD_INVALID` or `VALUE_OUT_OF_RANGE`." }, "message": { "type": "string", "description": "Human-readable, non-localized explanation of this individual failure." }, "target": { "type": "string", "description": "What this failure refers to, e.g. the violated field." } }, "required": [ "code", "message" ] } }, "responses": { "BadRequest": { "description": "The request could not be understood. `BAD_REQUEST` for a body that does not decode — its `message` names the property at fault — and `VALIDATION_FAILED` with one `details` entry per offending parameter for a malformed request target (an unknown query parameter or sort key). Also `BAD_REQUEST` for a response unit naming a channel this client cannot reference.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": { "code": "BAD_REQUEST", "message": "The request is invalid." } } } } }, "Unauthorized": { "description": "Authentication is required or the supplied credentials are invalid.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": { "code": "UNAUTHORIZED", "message": "Authentication is required to access this resource." } } } } }, "Forbidden": { "description": "The caller lacks the permission for this operation on this resource (`FORBIDDEN`).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": { "code": "FORBIDDEN", "message": "Access to this resource is denied." } } } } }, "NotFound": { "description": "The requested resource does not exist. The code is resource-specific, e.g. `PARTNER_NOT_FOUND`, `PROFILE_NOT_FOUND` or `CHANNEL_NOT_FOUND`.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": { "code": "PARTNER_NOT_FOUND", "message": "Partner not found: 42" } } } } }, "Conflict": { "description": "The request collides with the current state of the resource: a name already taken by another record, a `lastModified` that no longer matches because the record changed since it was read, or a delete the record's state refuses (it is open in the Lobster UI, still referenced by other objects, or managed by the Transport Manager). A field-level collision carries one `details` entry naming it.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": { "code": "CONFLICT", "message": "The request conflicts with the current state of the resource.", "details": [ { "code": "FIELD_INVALID", "message": "A partner with the name 'ACME' already exists.", "target": "name" } ] } } } } }, "UnprocessableEntity": { "description": "The body decoded but breaks a rule of the resource: a required member is missing, a value is not one of the accepted values or violates its pattern, length or range, a referenced id (partner, certificate, profile) does not exist, or two members contradict each other. One `details` entry per violation: `FIELD_REQUIRED` or `FIELD_INVALID`, with `target` naming the member path and `message` the rule, including the accepted values where there is a fixed set.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": { "code": "VALIDATION_FAILED", "message": "Request validation failed", "details": [ { "code": "FIELD_REQUIRED", "message": "Field 'name' must not be empty.", "target": "name" } ] } } } } }, "ServerError": { "description": "An unexpected server error occurred.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred." } } } } } }, "securitySchemes": { "OAuth2": { "type": "oauth2", "description": "OAuth2 client-credentials flow for machine-to-machine access.\nExchange a client id/secret at `/dw/register/oauth/token` for a bearer token, then send it\nas `Authorization: Bearer `. Client credentials are provisioned in the\nLobster administration UI.\n\nThis is the client-credentials token endpoint of the Platform API. `/oauth/token`, the\n`token_endpoint` advertised at `/.well-known/oauth-authorization-server`, serves the authorization\ncode flow of the `OAuth2AuthorizationCode` scheme.", "flows": { "clientCredentials": { "tokenUrl": "/dw/register/oauth/token", "refreshUrl": "/dw/register/oauth/token", "scopes": {} } } }, "OAuth2AuthorizationCode": { "type": "oauth2", "description": "OAuth 2.1 authorization code flow with PKCE, for acting as a signed-in user. It works with Microsoft and other single sign-on providers: the provider only confirms the user's identity to the platform, which then issues its own token.\n\n1. `POST /oauth/register` (no authentication) with the JSON body `{\"redirect_uris\": [\"\"]}` returns a `client_id`. The user's browser has to reach the redirect URI.\n2. Open `/oauth/authorize` in the user's browser with `response_type=code`, `client_id`, `redirect_uri`, `state` and a `code_challenge` with `code_challenge_method=S256`. `state` is a fresh unguessable value per request, and `code_challenge` is the S256 hash of a `code_verifier` freshly generated per request from a cryptographically secure random source (43 to 128 characters, RFC 7636). The user signs in on the platform's login page, and the browser is redirected to the redirect URI with `code` and `state`; a callback whose `state` differs from the one sent is to be rejected.\n3. The code is valid for 30 seconds. Exchange it at `POST /oauth/token`, form-encoded, with `grant_type=authorization_code`, `code`, `redirect_uri`, `code_verifier` and `client_id`.\n4. The answer carries `access_token` (valid 30 minutes), `refresh_token` (valid 48 hours) and `expires_in` **in milliseconds**. Refresh with `grant_type=refresh_token`, `refresh_token` and `client_id`.", "flows": { "authorizationCode": { "authorizationUrl": "/oauth/authorize", "tokenUrl": "/oauth/token", "refreshUrl": "/oauth/token", "scopes": {} } } }, "SessionBearer": { "type": "http", "description": "Bearer token obtained from an authenticated browser or guest-user session.\n\n**Flow 1 — UI login:** Log in via the Lobster web UI at `/`, then call\n`GET /auth/sessionBearerToken` to exchange the session cookie for a bearer token.\n\n**Flow 2 — Guest user login token:** Append a GuestUser `loginToken` as a URL\nquery parameter to the base URL to establish a password-free session:\n```\nGET ?loginToken=\n```\nThen call `GET /auth/sessionBearerToken` to obtain the bearer token.", "scheme": "bearer" } } } } ````