openapi: 3.0.3 info: title: Webhook Privacy Configuration - KPN description: | KPN delivers outbound webhook notifications — such as SMS delivery reports — to the endpoints you configure. This API lets you control two things about those deliveries: the URL they are sent to, and which fields are included in the payload. **How configuration scopes work** You can configure webhooks at three levels — Organization, Team, or Application. Settings resolve from the most specific level to the broadest: an Application config overrides a Team config, which overrides the Organization config. This lets you set sensible defaults at org or team level and override them only where a specific application needs it. **Controlling payload fields (privacy)** `privacy_config.excluded_fields` maps a service name to the list of fields to omit from that service's outbound payloads. Any field not listed is included; an empty or absent map means every field is sent. Exclusion rules resolve along the same Application → Team → Organization cascade. For example, to hide the recipient phone number and message body from SMS delivery reports: ```json { "privacy_config": { "excluded_fields": { "sms_dlr": ["RecipientPhonenumber", "Message"] } } } ``` **Signing keys are managed separately** The `signing` block returned by these endpoints is read-only. To create and rotate the keys used to sign outbound payloads, use the Webhook Signing Keys API. **Authentication** You need an OAuth 2.0 Bearer token to call these endpoints. Exchange your **Client ID** and **Client Secret** (available in the [KPN API Store](https://developer.kpn.com)) for an access token, then pass it as `Authorization: Bearer ` on every request. Tokens expire, so build in a refresh before expiry. **Need help?** - [KPN Developer Portal](https://developer.kpn.com) - [Getting Started with KPN APIs](https://developer.kpn.com/getting-started) - [API Support](https://developer.kpn.com/support) version: 3.0.0 contact: name: API Support email: api_developer@kpn.com url: https://developer.kpn.com/support termsOfService: https://developer.kpn.com/legal servers: # Added by API Auto Mocking Plugin - description: SwaggerHub API Auto Mocking url: https://virtserver.swaggerhub.com/kpn/webhook-config-management-kpn/2.0.0 - url: https://api-prd.kpn.com/webhookconfigs-kpn description: Production tags: - name: Organization description: | Organization-scope webhook configuration. Applies to all teams and applications in your organization unless a team or application config overrides it. - name: Team description: | Team-scope webhook configuration — webhook URL and field exclusions. Overrides the organization config for all applications in your team unless an application config is set. - name: Application description: | Application-scope webhook configuration — webhook URL and field exclusions. Highest precedence — overrides both team and organization config for this specific application. security: - OAuth2: [] paths: # ─── Organization ───────────────────────────────────────────────────────────── /organizations: get: operationId: getOrganizationWebhookConfig tags: [Organization] summary: Get organization webhook config description: | Returns the webhook configuration for your organization, including any active field exclusion rules and signing key status. The organization config record is created automatically when the first org-level signing key is provisioned or when the first webhook delivery is processed for your organization. responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/OrgWebhookConfigResponse' example: organization_id: org_abc123 scope_type: ORGANIZATION privacy_config: excluded_fields: sms_dlr: [RecipientPhonenumber] signing: active_key_id: wk_2C6EDCDFDFD944F3A75D0D36 created_at: '2026-06-01T09:00:00.000Z' updated_at: '2026-06-10T12:00:00.000Z' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' put: operationId: updateOrganizationWebhookConfig tags: [Organization] summary: Update organization privacy config description: | Updates the org-level field exclusion settings. All teams and applications in your organization inherit these settings unless they define their own. To manage signing keys, use the [Webhook Signing Keys API](#tag/Organization-Keys). requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/OrgWebhookConfigUpdate' examples: excludeFields: summary: Exclude sensitive fields from SMS delivery reports value: privacy_config: excluded_fields: sms_dlr: [RecipientPhonenumber, Message] clearExclusions: summary: Include all fields (clear exclusions) value: privacy_config: excluded_fields: {} responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/OrgWebhookConfigResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': description: Organization config not found — provision an org-level signing key first. content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '500': $ref: '#/components/responses/InternalServerError' # ─── Team ───────────────────────────────────────────────────────────────────── /teams: post: operationId: createTeamWebhookConfig tags: [Team] summary: Create team webhook config description: | Creates the webhook configuration for your team, including the URL where KPN will deliver outbound webhook notifications and any field exclusion rules. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TeamWebhookConfigRequest' examples: basic: summary: Webhook URL only value: webhook_url: https://webhook.example.com/kpn/dlr withPrivacy: summary: With field exclusions value: webhook_url: https://webhook.example.com/kpn/dlr privacy_config: excluded_fields: sms_dlr: [RecipientPhonenumber, Message] responses: '201': description: Created content: application/json: schema: $ref: '#/components/schemas/WebhookConfigResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '500': $ref: '#/components/responses/InternalServerError' get: operationId: getTeamWebhookConfig tags: [Team] summary: Get team webhook config description: Returns the current webhook configuration for your team. responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/WebhookConfigResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' put: operationId: updateTeamWebhookConfig tags: [Team] summary: Update team webhook config description: Updates the webhook URL and/or field exclusion settings for your team. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TeamWebhookConfigRequest' examples: updateUrl: summary: Change webhook URL value: webhook_url: https://webhook.example.com/kpn/dlr-v2 updatePrivacy: summary: Update exclusions value: webhook_url: https://webhook.example.com/kpn/dlr-v2 privacy_config: excluded_fields: sms_dlr: [DLRID, MessageType] responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/WebhookConfigResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' delete: operationId: deleteTeamWebhookConfig tags: [Team] summary: Delete team webhook config description: | Permanently removes the team webhook configuration. Webhook deliveries will fall back to any configured org-level settings. responses: '204': description: Deleted '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' # ─── Application ────────────────────────────────────────────────────────────── /applications: post: operationId: createApplicationWebhookConfig tags: [Application] summary: Create application webhook config description: | Creates the webhook configuration for a specific application in your team. Application settings take highest precedence and override team and org settings. parameters: - $ref: '#/components/parameters/ApplicationName' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AppWebhookConfigRequest' examples: basic: summary: Webhook URL only value: webhook_url: https://webhook.example.com/kpn/app/dlr withPrivacy: summary: With field exclusions value: webhook_url: https://webhook.example.com/kpn/app/dlr privacy_config: excluded_fields: sms_dlr: [Message, CustomerId] responses: '201': description: Created content: application/json: schema: $ref: '#/components/schemas/WebhookConfigResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '500': $ref: '#/components/responses/InternalServerError' get: operationId: getApplicationWebhookConfig tags: [Application] summary: Get application webhook config description: Returns the current webhook configuration for your application. parameters: - $ref: '#/components/parameters/ApplicationName' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/WebhookConfigResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' put: operationId: updateApplicationWebhookConfig tags: [Application] summary: Update application webhook config description: Updates the webhook URL and/or field exclusion settings for your application. parameters: - $ref: '#/components/parameters/ApplicationName' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AppWebhookConfigRequest' examples: update: summary: Update URL and exclusions value: webhook_url: https://webhook.example.com/kpn/app/dlr-v2 privacy_config: excluded_fields: sms_dlr: [DLRID] responses: '200': description: Updated content: application/json: schema: $ref: '#/components/schemas/WebhookConfigResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' delete: operationId: deleteApplicationWebhookConfig tags: [Application] summary: Delete application webhook config description: | Permanently removes the application webhook configuration. Webhook deliveries for this application will fall back to team-level settings. responses: '204': description: Deleted '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' components: parameters: ApplicationName: in: header name: x-application-name required: false schema: type: string description: Human-readable name for your application. Optional; used for display purposes only. securitySchemes: OAuth2: type: oauth2 flows: clientCredentials: tokenUrl: https://api-prd.kpn.com/oauth/client_credential/accesstoken?grant_type=client_credentials scopes: {} responses: BadRequest: description: Bad request — check your request body for missing or invalid fields. content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' example: errorResponse: code: "400" message: "Bad Request" info: "https://developer.kpn.com/documentation-webhook-config" Unauthorized: description: Unauthorized — missing or invalid Bearer token. content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' example: errorResponse: code: "401" message: "Unauthorized" info: "https://developer.kpn.com/getting-started" Forbidden: description: Forbidden — your token does not have permission to access this resource. content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' example: errorResponse: code: "403" message: "Forbidden" info: "https://developer.kpn.com/support" NotFound: description: Not found — the requested configuration does not exist. content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' example: errorResponse: code: "404" message: "Not Found" info: "https://developer.kpn.com/documentation-webhook-config" InternalServerError: description: Internal server error. content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' example: errorResponse: code: "500" message: "Internal Server Error" info: "https://developer.kpn.com/support" schemas: ApiErrorResponse: type: object properties: errorResponse: type: object properties: code: type: string description: HTTP status code as a string. example: "400" message: type: string description: Human-readable error message. example: "Bad Request" info: type: string description: URL to relevant documentation or support page. example: "https://developer.kpn.com/documentation-webhook-config" PrivacyConfig: type: object description: | Service-scoped field exclusion map. Keys are KPN service identifiers (e.g. `sms_dlr`); values are lists of field names to omit from outbound webhook payloads for that service. Any field not listed is included in the payload. An empty or absent map means **include all fields**. properties: excluded_fields: type: object additionalProperties: type: array items: type: string maxItems: 50 example: sms_dlr: [RecipientPhonenumber, Message] OrgWebhookConfigUpdate: type: object properties: privacy_config: $ref: '#/components/schemas/PrivacyConfig' OrgWebhookConfigResponse: type: object properties: organization_id: type: string description: Your organization identifier. scope_type: type: string enum: [ORGANIZATION] privacy_config: $ref: '#/components/schemas/PrivacyConfig' signing: type: object description: Read-only. Signing key status — manage keys via the Webhook Signing Keys API. properties: active_key_id: type: string nullable: true description: ID of the currently active signing key for this scope. created_at: type: string format: date-time nullable: true updated_at: type: string format: date-time nullable: true TeamWebhookConfigRequest: type: object required: [webhook_url] properties: webhook_url: type: string format: uri maxLength: 2048 description: HTTPS URL where KPN will POST outbound webhook notifications. example: https://webhook.example.com/kpn/dlr privacy_config: $ref: '#/components/schemas/PrivacyConfig' AppWebhookConfigRequest: type: object required: [webhook_url] properties: webhook_url: type: string format: uri maxLength: 2048 description: HTTPS URL where KPN will POST outbound webhook notifications for this application. example: https://webhook.example.com/kpn/app/dlr privacy_config: $ref: '#/components/schemas/PrivacyConfig' WebhookConfigResponse: type: object properties: scope_type: type: string enum: [CUSTOMER, APPLICATION] description: "`CUSTOMER` for team-scoped configs; `APPLICATION` for app-scoped configs." webhook_url: type: string format: uri description: The URL KPN delivers webhook notifications to. privacy_config: $ref: '#/components/schemas/PrivacyConfig' signing: type: object description: Read-only signing key status. properties: active_key_id: type: string nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time