# Privilege

## List privileges for the specified pass id.

> Retrieves all privileges for a specific pass using its identifier.\
> Convenience endpoint when the pass ID is already known.\
> \
> \## Authorization\
> Requires \`Pass.Read\` scope.\
> \
> \## Sorting\
> Privileges are returned in priority order (highest to lowest).

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"Privilege":{"required":["privilegeId"],"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeBase"}],"properties":{"privilegeId":{"type":["null","string"],"description":"Unique identifier of the privilege (unique across all passes within the tenant)."}},"additionalProperties":false,"description":"Represents a persisted privilege with a required unique identifier."},"PrivilegeBase":{"required":["type"],"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance (e.g., 100 > 10).","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"type":{"$ref":"#/components/schemas/PrivilegeType"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base model for privilege definitions, including classification, visuals, links, and state."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/{passId}/privileges":{"get":{"tags":["Privilege"],"summary":"List privileges for the specified pass id.","description":"Retrieves all privileges for a specific pass using its identifier.\nConvenience endpoint when the pass ID is already known.\n\n## Authorization\nRequires `Pass.Read` scope.\n\n## Sorting\nPrivileges are returned in priority order (highest to lowest).","parameters":[{"name":"passId","in":"path","description":"Pass id.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Privileges returned","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Privilege"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Privilege"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Privilege"}}}}},"404":{"description":"Pass not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Create a privilege for the specified pass id.

> Creates a new privilege using the pass identifier directly. Use the PUT variants with a\
> privilegeId in the route for idempotent upsert semantics.\
> This is a convenience endpoint for scenarios where the pass ID is already known.\
> \
> \## Authorization\
> Requires \`Pass.Write\` scope.\
> \
> \## Behavior\
> Same as the identifiers-based variant but uses a path parameter instead of query identifiers.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"InsertPrivilegeRequest":{"required":["type"],"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeRequestBase"}],"properties":{"type":{"$ref":"#/components/schemas/PrivilegeType"},"options":{"$ref":"#/components/schemas/InsertOptions"}},"additionalProperties":false,"description":"Request model to create a new privilege."},"PrivilegeRequestBase":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance.","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base request model for privilege operations."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"InsertOptions":{"type":"object","properties":{"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."},"notification":{"$ref":"#/components/schemas/NotifyRequest"}},"additionalProperties":false,"description":"Configuration options for privilege creation, including correlation tracking and notifications."},"NotifyRequest":{"type":"object","properties":{"content":{"type":["null","string"],"description":"Could be null if LocalizedContent is specified"},"localizedContent":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized notification content by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The notification content for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}},"options":{"$ref":"#/components/schemas/NotifyRequestOptions"}},"additionalProperties":false},"NotifyRequestOptions":{"type":"object","properties":{"updateData":{"type":"boolean","description":"Indicate if pass data should also be updated when the notification is sent.","default":false},"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."}},"additionalProperties":false},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/{passId}/privileges":{"post":{"tags":["Privilege"],"summary":"Create a privilege for the specified pass id.","description":"Creates a new privilege using the pass identifier directly. Use the PUT variants with a\nprivilegeId in the route for idempotent upsert semantics.\nThis is a convenience endpoint for scenarios where the pass ID is already known.\n\n## Authorization\nRequires `Pass.Write` scope.\n\n## Behavior\nSame as the identifiers-based variant but uses a path parameter instead of query identifiers.","parameters":[{"name":"passId","in":"path","description":"Pass id.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Privilege payload to create.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsertPrivilegeRequest"}},"text/json":{"schema":{"$ref":"#/components/schemas/InsertPrivilegeRequest"}},"application/*+json":{"schema":{"$ref":"#/components/schemas/InsertPrivilegeRequest"}}}},"responses":{"200":{"description":"Privilege queued"},"404":{"description":"Pass not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Retrieve a privilege for a specific pass.

> Fetches a single privilege belonging to a specific pass.\
> Ensures both the pass and privilege exist and are correctly associated.\
> \
> \## Authorization\
> Requires \`Pass.Read\` scope.\
> \
> \## Validation\
> Returns 404 if either the pass or the privilege is missing,\
> or if the privilege does not belong to the specified pass.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"Privilege":{"required":["privilegeId"],"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeBase"}],"properties":{"privilegeId":{"type":["null","string"],"description":"Unique identifier of the privilege (unique across all passes within the tenant)."}},"additionalProperties":false,"description":"Represents a persisted privilege with a required unique identifier."},"PrivilegeBase":{"required":["type"],"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance (e.g., 100 > 10).","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"type":{"$ref":"#/components/schemas/PrivilegeType"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base model for privilege definitions, including classification, visuals, links, and state."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/{passId}/privileges/{privilegeId}":{"get":{"tags":["Privilege"],"summary":"Retrieve a privilege for a specific pass.","description":"Fetches a single privilege belonging to a specific pass.\nEnsures both the pass and privilege exist and are correctly associated.\n\n## Authorization\nRequires `Pass.Read` scope.\n\n## Validation\nReturns 404 if either the pass or the privilege is missing,\nor if the privilege does not belong to the specified pass.","parameters":[{"name":"passId","in":"path","description":"Pass identifier.","required":true,"schema":{"type":"string"}},{"name":"privilegeId","in":"path","description":"Privilege identifier.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Privilege returned","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Privilege"}},"application/json":{"schema":{"$ref":"#/components/schemas/Privilege"}},"text/json":{"schema":{"$ref":"#/components/schemas/Privilege"}}}},"404":{"description":"Pass or privilege not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Upsert (idempotent) a privilege for the specified pass id.

> Creates or updates a privilege with the specified \`privilegeId\` for the given pass.\
> This endpoint is idempotent: repeated calls with the same payload produce the same result.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"PatchPrivilegeRequest":{"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeRequestBase"}],"properties":{"type":{"$ref":"#/components/schemas/PrivilegeType"},"options":{"$ref":"#/components/schemas/PatchOptions"}},"additionalProperties":false,"description":"Request model to patch an existing privilege."},"PrivilegeRequestBase":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance.","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base request model for privilege operations."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"PatchOptions":{"type":"object","properties":{"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."},"notification":{"$ref":"#/components/schemas/NotifyRequest"}},"additionalProperties":false,"description":"Configuration options for privilege patching, including correlation tracking and notifications."},"NotifyRequest":{"type":"object","properties":{"content":{"type":["null","string"],"description":"Could be null if LocalizedContent is specified"},"localizedContent":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized notification content by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The notification content for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}},"options":{"$ref":"#/components/schemas/NotifyRequestOptions"}},"additionalProperties":false},"NotifyRequestOptions":{"type":"object","properties":{"updateData":{"type":"boolean","description":"Indicate if pass data should also be updated when the notification is sent.","default":false},"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."}},"additionalProperties":false},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/{passId}/privileges/{privilegeId}":{"put":{"tags":["Privilege"],"summary":"Upsert (idempotent) a privilege for the specified pass id.","description":"Creates or updates a privilege with the specified `privilegeId` for the given pass.\nThis endpoint is idempotent: repeated calls with the same payload produce the same result.","parameters":[{"name":"passId","in":"path","description":"Pass id.","required":true,"schema":{"type":"string"}},{"name":"privilegeId","in":"path","description":"Unique identifier of the privilege to upsert.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Privilege payload to upsert.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchPrivilegeRequest"}},"text/json":{"schema":{"$ref":"#/components/schemas/PatchPrivilegeRequest"}},"application/*+json":{"schema":{"$ref":"#/components/schemas/PatchPrivilegeRequest"}}}},"responses":{"200":{"description":"Privilege upsert queued or applied"},"404":{"description":"Pass not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Delete a privilege for a specific pass.

> Removes a privilege from a specific pass.\
> Both the pass and privilege must exist.\
> \
> \## Authorization\
> Requires \`Pass.Write\` scope.\
> \
> \## Scope\
> This operation only affects the privilege with the specified pass.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/{passId}/privileges/{privilegeId}":{"delete":{"tags":["Privilege"],"summary":"Delete a privilege for a specific pass.","description":"Removes a privilege from a specific pass.\nBoth the pass and privilege must exist.\n\n## Authorization\nRequires `Pass.Write` scope.\n\n## Scope\nThis operation only affects the privilege with the specified pass.","parameters":[{"name":"passId","in":"path","description":"Pass identifier.","required":true,"schema":{"type":"string"}},{"name":"privilegeId","in":"path","description":"Privilege identifier.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Privilege deleted"},"404":{"description":"Pass or privilege not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## List privileges for the pass resolved from identifiers.

> Retrieves all privileges associated with a pass using query identifiers.\
> Privileges are sorted by priority (highest first) and movements within each privilege are ordered by date (oldest first).\
> \
> \## Authorization\
> Requires \`Pass.Read\` scope.\
> \
> \## Use Cases\
> \- Display available offers and benefits to the pass holder\
> \- Check current loyalty balance or punch card progress\
> \- Verify privilege availability before redemption

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"Privilege":{"required":["privilegeId"],"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeBase"}],"properties":{"privilegeId":{"type":["null","string"],"description":"Unique identifier of the privilege (unique across all passes within the tenant)."}},"additionalProperties":false,"description":"Represents a persisted privilege with a required unique identifier."},"PrivilegeBase":{"required":["type"],"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance (e.g., 100 > 10).","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"type":{"$ref":"#/components/schemas/PrivilegeType"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base model for privilege definitions, including classification, visuals, links, and state."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/privileges":{"get":{"tags":["Privilege"],"summary":"List privileges for the pass resolved from identifiers.","description":"Retrieves all privileges associated with a pass using query identifiers.\nPrivileges are sorted by priority (highest first) and movements within each privilege are ordered by date (oldest first).\n\n## Authorization\nRequires `Pass.Read` scope.\n\n## Use Cases\n- Display available offers and benefits to the pass holder\n- Check current loyalty balance or punch card progress\n- Verify privilege availability before redemption","parameters":[{"name":"identifiers","in":"query","description":"Pass identifiers (internal or external) used to resolve the pass.","schema":{"type":"object","additionalProperties":{"type":"string"}}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Privileges returned","content":{"text/plain":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Privilege"}}},"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Privilege"}}},"text/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Privilege"}}}}},"404":{"description":"Pass not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Create a privilege for the pass identified by the supplied identifiers.

> Creates a new privilege for the specified pass. Use the PUT variants with a\
> privilegeId in the route for idempotent upsert semantics.\
> Privileges represent benefits, offers, or entitlements tied to a pass.\
> \
> \## Authorization\
> Requires \`Pass.Write\` scope.\
> \
> \## Operation\
> When a privilege is applied, the system queues it for processing.\
> Optional notification can be sent to the pass holder upon application.\
> \
> \## Use Cases\
> \- Adding loyalty points or rewards\
> \- Issuing promotional offers\
> \- Granting membership benefits

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"InsertPrivilegeRequest":{"required":["type"],"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeRequestBase"}],"properties":{"type":{"$ref":"#/components/schemas/PrivilegeType"},"options":{"$ref":"#/components/schemas/InsertOptions"}},"additionalProperties":false,"description":"Request model to create a new privilege."},"PrivilegeRequestBase":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance.","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base request model for privilege operations."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"InsertOptions":{"type":"object","properties":{"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."},"notification":{"$ref":"#/components/schemas/NotifyRequest"}},"additionalProperties":false,"description":"Configuration options for privilege creation, including correlation tracking and notifications."},"NotifyRequest":{"type":"object","properties":{"content":{"type":["null","string"],"description":"Could be null if LocalizedContent is specified"},"localizedContent":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized notification content by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The notification content for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}},"options":{"$ref":"#/components/schemas/NotifyRequestOptions"}},"additionalProperties":false},"NotifyRequestOptions":{"type":"object","properties":{"updateData":{"type":"boolean","description":"Indicate if pass data should also be updated when the notification is sent.","default":false},"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."}},"additionalProperties":false},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/privileges":{"post":{"tags":["Privilege"],"summary":"Create a privilege for the pass identified by the supplied identifiers.","description":"Creates a new privilege for the specified pass. Use the PUT variants with a\nprivilegeId in the route for idempotent upsert semantics.\nPrivileges represent benefits, offers, or entitlements tied to a pass.\n\n## Authorization\nRequires `Pass.Write` scope.\n\n## Operation\nWhen a privilege is applied, the system queues it for processing.\nOptional notification can be sent to the pass holder upon application.\n\n## Use Cases\n- Adding loyalty points or rewards\n- Issuing promotional offers\n- Granting membership benefits","parameters":[{"name":"identifiers","in":"query","description":"Pass identifiers (internal or external) used to resolve the pass.","schema":{"type":"object","additionalProperties":{"type":"string"}}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Privilege payload to create.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsertPrivilegeRequest"}},"text/json":{"schema":{"$ref":"#/components/schemas/InsertPrivilegeRequest"}},"application/*+json":{"schema":{"$ref":"#/components/schemas/InsertPrivilegeRequest"}}}},"responses":{"200":{"description":"Privilege queued"},"404":{"description":"Pass not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Retrieve a privilege by its id.

> Fetches detailed information about a specific privilege across all passes in the tenant.\
> Returns complete privilege metadata including content, appearance, and current state.\
> \
> \## Authorization\
> Requires \`Pass.Read\` scope.\
> \
> \## Use Cases\
> \- View privilege details for display or validation\
> \- Check privilege expiration or availability status\
> \- Retrieve localized content for multiple languages

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"Privilege":{"required":["privilegeId"],"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeBase"}],"properties":{"privilegeId":{"type":["null","string"],"description":"Unique identifier of the privilege (unique across all passes within the tenant)."}},"additionalProperties":false,"description":"Represents a persisted privilege with a required unique identifier."},"PrivilegeBase":{"required":["type"],"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance (e.g., 100 > 10).","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"type":{"$ref":"#/components/schemas/PrivilegeType"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base model for privilege definitions, including classification, visuals, links, and state."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/privileges/{privilegeId}":{"get":{"tags":["Privilege"],"summary":"Retrieve a privilege by its id.","description":"Fetches detailed information about a specific privilege across all passes in the tenant.\nReturns complete privilege metadata including content, appearance, and current state.\n\n## Authorization\nRequires `Pass.Read` scope.\n\n## Use Cases\n- View privilege details for display or validation\n- Check privilege expiration or availability status\n- Retrieve localized content for multiple languages","parameters":[{"name":"privilegeId","in":"path","description":"Privilege identifier.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Privilege returned","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/Privilege"}},"application/json":{"schema":{"$ref":"#/components/schemas/Privilege"}},"text/json":{"schema":{"$ref":"#/components/schemas/Privilege"}}}},"404":{"description":"Privilege not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Upsert (idempotent) a privilege for the pass identified by the supplied identifiers.

> Creates or updates a privilege with the specified \`privilegeId\` for the resolved pass.\
> This endpoint is idempotent: repeated calls with the same payload produce the same result.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"PatchPrivilegeRequest":{"type":"object","allOf":[{"$ref":"#/components/schemas/PrivilegeRequestBase"}],"properties":{"type":{"$ref":"#/components/schemas/PrivilegeType"},"options":{"$ref":"#/components/schemas/PatchOptions"}},"additionalProperties":false,"description":"Request model to patch an existing privilege."},"PrivilegeRequestBase":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier for the privilege in the source system."},"priority":{"type":["null","integer"],"description":"Priority of the privilege. Larger numbers indicate higher importance.","format":"int32"},"origin":{"$ref":"#/components/schemas/PrivilegeOrigin"},"categories":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeCategory"},"description":"Categories used to classify and filter the privilege."},"content":{"$ref":"#/components/schemas/PrivilegeContent"},"appearance":{"$ref":"#/components/schemas/PrivilegeAppearance"},"links":{"$ref":"#/components/schemas/PrivilegeLinks"},"data":{"$ref":"#/components/schemas/PrivilegeData"},"deletionDate":{"type":["null","string"],"description":"The timestamp at which this privilege should be removed from the system.","format":"date-time"}},"additionalProperties":false,"description":"Base request model for privilege operations."},"PrivilegeOrigin":{"type":"object","properties":{"externalId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"External identifier of this privilege in the partner system."},"generator":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Name of the partner or upstream system that generated the privilege."},"processId":{"maxLength":100,"minLength":1,"type":["null","string"],"description":"Identifier of the upstream process or job that created this privilege."}},"additionalProperties":false,"description":"Describes the origin of a privilege in an external/partner system."},"PrivilegeCategory":{"enum":["Other","Gift","Access","AudioGuide"],"type":"string","description":"High-level classification of privileges for organization and filtering."},"PrivilegeContent":{"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"description":{"$ref":"#/components/schemas/LocalizedString"}},"additionalProperties":false,"description":"Localized content for a privilege (title, description, notifications)."},"LocalizedString":{"type":"object","properties":{"value":{"type":["null","string"],"description":"The default text in the primary language."},"values":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized translations by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The translated string for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}}},"additionalProperties":false,"description":"Represents a localized string with a default value and optional per-language translations."},"PrivilegeAppearance":{"type":"object","properties":{"mainImageUrl":{"$ref":"#/components/schemas/LocalizedString"},"thumbnailUrl":{"$ref":"#/components/schemas/LocalizedString"},"backgroundColor":{"type":["null","string"],"description":"Background color (e.g., HEX code)."},"foregroundColor":{"type":["null","string"],"description":"Foreground color for text or icons (e.g., HEX code)."}},"additionalProperties":false,"description":"Visual appearance settings for a privilege."},"PrivilegeLinks":{"type":"object","properties":{"legalInformation":{"$ref":"#/components/schemas/PrivilegeLink"},"callToAction":{"$ref":"#/components/schemas/PrivilegeLink"}},"additionalProperties":false,"description":"A set of related links associated with a privilege."},"PrivilegeLink":{"required":["link"],"type":"object","properties":{"title":{"$ref":"#/components/schemas/LocalizedString"},"link":{"type":["null","string"],"description":"Target URI of the link.","format":"uri"}},"additionalProperties":false,"description":"A single link with a localized title and a target URI."},"PrivilegeData":{"type":"object","properties":{"value":{"type":["null","number"],"description":"Current numeric value of the privilege (e.g., loyalty points, punch count).\nThis is computed as the sum of all movement values. Can be negative if partially redeemed or adjusted. \nCan be fractional for progress-based privileges.","format":"double"},"movements":{"type":["null","array"],"items":{"$ref":"#/components/schemas/PrivilegeMovement"},"description":"History of all movements (transactions) affecting this privilege's data.\nThe current value is computed as the sum of all movement values."},"content":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional provider-specific payload or metadata for the privilege data."}},"additionalProperties":false,"description":"Runtime state and payload associated with a privilege."},"PrivilegeMovement":{"required":["date","movementId","value"],"type":"object","properties":{"movementId":{"type":["null","string"],"description":"Unique identifier for this movement."},"date":{"type":"string","description":"Timestamp when this movement occurred.","format":"date-time"},"value":{"type":"number","description":"Change in value. Negative when the privilege is used/redeemed.\nFractional for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Represents a single movement or transaction affecting a privilege's value."},"PrivilegeType":{"enum":["OneTime","Unlimited","MultiUse","Unlockable"],"type":"string","description":"Defines how a privilege behaves from a usage perspective."},"PatchOptions":{"type":"object","properties":{"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."},"notification":{"$ref":"#/components/schemas/NotifyRequest"}},"additionalProperties":false,"description":"Configuration options for privilege patching, including correlation tracking and notifications."},"NotifyRequest":{"type":"object","properties":{"content":{"type":["null","string"],"description":"Could be null if LocalizedContent is specified"},"localizedContent":{"type":["null","object"],"additionalProperties":{"type":"string"},"description":"Localized notification content by language code.\nKey: ISO 639-1 code or \"iso2-region\" (e.g., \"en\", \"en-US\").\nValue: The notification content for that language.","propertyNames":{"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}},"options":{"$ref":"#/components/schemas/NotifyRequestOptions"}},"additionalProperties":false},"NotifyRequestOptions":{"type":"object","properties":{"updateData":{"type":"boolean","description":"Indicate if pass data should also be updated when the notification is sent.","default":false},"correlationId":{"maxLength":100,"minLength":10,"type":["null","string"],"description":"Correlation identifier to group and trace related API calls."}},"additionalProperties":false},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/privileges/{privilegeId}":{"put":{"tags":["Privilege"],"summary":"Upsert (idempotent) a privilege for the pass identified by the supplied identifiers.","description":"Creates or updates a privilege with the specified `privilegeId` for the resolved pass.\nThis endpoint is idempotent: repeated calls with the same payload produce the same result.","parameters":[{"name":"identifiers","in":"query","description":"Pass identifiers (internal or external) used to resolve the pass.","schema":{"type":"object","additionalProperties":{"type":"string"}}},{"name":"privilegeId","in":"path","description":"Unique identifier of the privilege to upsert.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Privilege payload to upsert.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchPrivilegeRequest"}},"text/json":{"schema":{"$ref":"#/components/schemas/PatchPrivilegeRequest"}},"application/*+json":{"schema":{"$ref":"#/components/schemas/PatchPrivilegeRequest"}}}},"responses":{"200":{"description":"Privilege upsert queued or applied"},"404":{"description":"Pass not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Delete a privilege by its id.

> Removes a privilege from the system entirely.\
> The privilege is deleted across all passes it may be associated with.\
> \
> \## Authorization\
> Requires \`Pass.Write\` scope.\
> \
> \## Irreversibility\
> This operation is permanent. The privilege cannot be recovered after deletion.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/privileges/{privilegeId}":{"delete":{"tags":["Privilege"],"summary":"Delete a privilege by its id.","description":"Removes a privilege from the system entirely.\nThe privilege is deleted across all passes it may be associated with.\n\n## Authorization\nRequires `Pass.Write` scope.\n\n## Irreversibility\nThis operation is permanent. The privilege cannot be recovered after deletion.","parameters":[{"name":"privilegeId","in":"path","description":"Privilege identifier.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Privilege deleted"},"404":{"description":"Privilege not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Apply a movement (transaction) to a privilege's value and return the created movement identifier.

> Records a change to a privilege's value (redemption, adjustment, issuance).\
> Movements are tracked in the privilege's history for audit purposes and form the basis for computing current value.\
> \
> \## Authorization\
> Requires \`Pass.Write\` scope.\
> \
> \## Concurrency Control\
> The \`OldValue\` parameter enables optimistic locking with server-side validation.\
> The handler compares the expected value (OldValue) to the current sum with epsilon tolerance (±0.0001).\
> This prevents race conditions when multiple clients attempt simultaneous updates.\
> If values differ beyond tolerance, returns 409 Conflict; if privilege is missing, returns 404 Not Found.\
> \
> \## Use Cases\
> \- Redeeming points or stamps (negative movement)\
> \- Issuing or adjusting loyalty balance (positive movement)\
> \- Applying promotional adjustments

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"Privilege"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["ScopedAuthorizeRequirement"]},{"apiKey":["ScopedAuthorizeRequirement"]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"ApplyMovementRequest":{"required":["movementValue","oldValue"],"type":"object","properties":{"oldValue":{"type":"number","description":"The expected sum of all movement values before this update.\nUsed for optimistic concurrency control with server-side validation in the handler.\nIf the current value differs, the request is rejected (409 Conflict).","format":"double"},"movementValue":{"type":"number","description":"The movement value to apply. Cannot be zero. Positive for issuance/award, negative for redemption/usage.\nFractional values are supported for progress-based privileges (e.g., 0.5 for half a stamp).","format":"double"},"remarks":{"maxLength":500,"minLength":1,"type":["null","string"],"description":"Optional remarks or debug information about this movement."}},"additionalProperties":false,"description":"Request model to apply a movement (transaction) to a privilege's value."},"MovementResponse":{"type":"object","properties":{"movementId":{"type":["null","string"]}},"additionalProperties":false,"description":"Response payload after a movement is created."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":["null","object"],"additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/privileges/{privilegeId}/movements":{"post":{"tags":["Privilege"],"summary":"Apply a movement (transaction) to a privilege's value and return the created movement identifier.","description":"Records a change to a privilege's value (redemption, adjustment, issuance).\nMovements are tracked in the privilege's history for audit purposes and form the basis for computing current value.\n\n## Authorization\nRequires `Pass.Write` scope.\n\n## Concurrency Control\nThe `OldValue` parameter enables optimistic locking with server-side validation.\nThe handler compares the expected value (OldValue) to the current sum with epsilon tolerance (±0.0001).\nThis prevents race conditions when multiple clients attempt simultaneous updates.\nIf values differ beyond tolerance, returns 409 Conflict; if privilege is missing, returns 404 Not Found.\n\n## Use Cases\n- Redeeming points or stamps (negative movement)\n- Issuing or adjusting loyalty balance (positive movement)\n- Applying promotional adjustments","parameters":[{"name":"privilegeId","in":"path","description":"Privilege identifier.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Movement request with concurrency check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyMovementRequest"}},"text/json":{"schema":{"$ref":"#/components/schemas/ApplyMovementRequest"}},"application/*+json":{"schema":{"$ref":"#/components/schemas/ApplyMovementRequest"}}}},"responses":{"200":{"description":"Movement applied successfully","content":{"text/plain":{"schema":{"$ref":"#/components/schemas/MovementResponse"}},"application/json":{"schema":{"$ref":"#/components/schemas/MovementResponse"}},"text/json":{"schema":{"$ref":"#/components/schemas/MovementResponse"}}}},"400":{"description":"MovementValue is zero","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"404":{"description":"Privilege not found","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"409":{"description":"Current value does not match OldValue (concurrency conflict)","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```
