{"record":{"id":"92d28e92d10181df","repo":"gotify/server","slug":"appid-is-required-when-not-authenticating-with-an","errorCode":null,"errorMessage":"appid is required when not authenticating with an application token","messagePattern":"appid is required when not authenticating with an application token","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"api/message.go","lineNumber":372,"sourceCode":"//\t        $ref: \"#/definitions/Error\"\n//\t  401:\n//\t    description: Unauthorized\n//\t    schema:\n//\t        $ref: \"#/definitions/Error\"\n//\t  403:\n//\t    description: Forbidden\n//\t    schema:\n//\t        $ref: \"#/definitions/Error\"\nfunc (a *MessageAPI) CreateMessage(ctx *gin.Context) {\n\tmessage := model.CreateMessage{}\n\tif err := ctx.Bind(&message); err != nil {\n\t\treturn\n\t}\n\n\tapp := auth.GetApplication(ctx)\n\tif app == nil {\n\t\tif message.ApplicationID == 0 {\n\t\t\tctx.AbortWithError(400, errors.New(\"appid is required when not authenticating with an application token\"))\n\t\t\treturn\n\t\t}\n\t\tfetchedApp, err := a.DB.GetApplicationByID(message.ApplicationID)\n\t\tif success := successOrAbort(ctx, 500, err); !success {\n\t\t\treturn\n\t\t}\n\t\tif fetchedApp == nil || fetchedApp.UserID != auth.GetUserID(ctx) {\n\t\t\tctx.AbortWithError(400, errors.New(\"appid not found\"))\n\t\t\treturn\n\t\t}\n\t\tapp = fetchedApp\n\t}\n\n\tmessage.ApplicationID = app.ID\n\tif strings.TrimSpace(message.Title) == \"\" {\n\t\tmessage.Title = app.Name\n\t}\n","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/gotify/server/blob/14bfc256276775c425f988d621dccfe705de18ac/api/message.go#L354-L390","documentation":"CreateMessage throws 400 'appid is required when not authenticating with an application token' when the request is authenticated as a client/user (not an app token) and the message body has no applicationID. Without an app token, Gotify cannot infer which application the message belongs to.","triggerScenarios":"POST /message with a client token or basic auth, no 'appid' (or appid: 0) in the JSON body.","commonSituations":"Reusing a client token meant for reading messages to also send messages; copying examples that use app tokens but authenticating differently; forgetting that appid is only optional when using an application token.","solutions":["Include \"appid\": <id> in the request body.","Or authenticate with an application token (Authorization: Bearer <app token> or X-Gotify-Key header) so appid can be inferred.","Create an application in the Gotify UI to obtain an app token."],"exampleFix":"// before\nPOST /message {\"title\":\"hi\",\"message\":\"hello\"} // client token, no appid\n// after\nPOST /message {\"appid\": 3, \"title\":\"hi\",\"message\":\"hello\"}\n// or use an app token instead of the client token","handlingStrategy":"validation","validationCode":"if (!authIsAppToken && !(body.appid > 0)) throw new Error('appid is required when not using an application token');","typeGuard":"function hasAppId(body) { return typeof body.appid === 'number' && Number.isInteger(body.appid) && body.appid > 0; }","tryCatchPattern":"try {\n  await gotify.post('/message', body);\n} catch (e) {\n  if (e.response?.status === 400 && /appid is required/.test(e.response.data)) {\n    body.appid = resolvedAppId; // retry with explicit app id\n  } else throw e;\n}","preventionTips":["Always send appid when authenticating with client tokens or basic auth.","Prefer application tokens for sending; client tokens for reading.","Keep a config mapping of app name -> appid/token.","Validate request bodies before sending."],"tags":["http-400","validation","gotify"],"backgroundTag":"missing-required-argument","analyzedSha":"14bfc256276775c425f988d621dccfe705de18ac","analyzedAt":"2026-09-05T12:52:36.781Z","contentChangedAt":"2026-09-05T12:52:36.781Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}