Create Global Policy
Endpoint
POST /apiops/projects/{projectName}/globalPolicies/
Authentication
Requires a Personal API Access Token.
Header
Authorization: Bearer YOUR_TOKEN
Request
Headers
| Header | Value | Required |
|---|---|---|
| Authorization | Bearer {token} | Yes |
| Content-Type | application/json | Yes |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| projectName | string | Yes | Project name |
Query Parameters
None
Request Body
The body is a polymorphic policy snapshot. The top-level "_class" field is required and selects
the concrete policy type — it must be one of the values listed under Supported Policy Types
below. The desired name is carried in the body's "name" field (not a URL path segment), so it can
contain characters that would not survive a URL path segment untouched.
Full JSON Body Example - WS-Security Username Token
{
"_class": "policy-ws-security-username",
"name": "backend-ws-security",
"description": "Username token injected before the request reaches the backend",
"active": true,
"username": "backend-service",
"password": "s3cr3t-already-encrypted-value-from-source-instance",
"passwordType": "PasswordText",
"mustUnderstand": true,
"nonce": true,
"created": true
}
The example above illustrates the cross-instance promotion contract:
passwordis the value exported from the source instance, which is already encrypted. It is persisted as-is — see Secret Contract below.
Common Fields (all policy types)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| _class | string | Yes | - | Policy type discriminator (see Supported Policy Types) |
| name | string | Yes | - | Global policy name — the value stored, not necessarily a URL segment |
| description | string | No | - | Policy description |
| active | boolean | No | false | Whether the policy is active |
| oneWay | boolean | No | false | Fire-and-forget execution flag |
| trace | boolean | No | false | Policy-level trace logging flag |
| buildCustomMessage | boolean | No | false | Whether a custom error message template is used |
| customMessageTemplate | string | No | - | Custom error message template (used when buildCustomMessage=true) |
| customMessageContentType | string | No | application/json; charset=UTF-8 | Content type of the custom error message |
| customMessageHttpStatusCode | integer | No | - | HTTP status code of the custom error message |
| policyCondition | object | No | - | Optional conditional-execution rule (same shape as the classic policy editors) |
Fields beyond this common set are specific to the chosen _class (in the example above: username,
password, passwordType, mustUnderstand, nonce, created are WS-Security Username Token
fields). id, projectId and global are always server-assigned and ignored if present in the body.
Secret Contract (POST vs PUT)
This endpoint is shared with cross-instance API Promotion, which exports a policy from a source instance and replays it here as-is. Because of that:
POST(this endpoint): any@SecretDatafield (e.g.passwordon WS-Security Username Token,clientSecreton OIDC) is expected to already be encrypted (as exported from the source instance) and is persisted unchanged — it is not re-encrypted.PUT(Update Global Policy) is the opposite:@SecretDatafields must be plaintext and are encrypted before persist.
Sending a plaintext secret to POST stores it in plaintext (it is never encrypted afterwards by this
endpoint). Sending an already-encrypted value to PUT double-encrypts it, corrupting the secret. Use
POST only for cross-instance snapshots that already carry encrypted secrets; use PUT for normal,
human-authored updates.
Supported Policy Types
The four MCP/A2A values were renamed so the wire value says who picks the target: -llm (the model picks it from its tool_use response) and -fixed (you pin one target). The old values — ai-mcp-tool-call, ai-mcp-tool-invoke, a2a-agent-call, a2a-agent-invoke — are still accepted on import, so packages exported before the rename keep working.
Full _class catalog
ai-a2a-call-fixed
ai-a2a-call-llm
ai-context-integrity
ai-dlp-guard
ai-loop-guard
ai-mcp-call-fixed
ai-mcp-call-llm
ai-pii-mask
ai-prompt-guard
ai-proxy
ai-rag-injection
ai-semantic-cache
ai-token-rate-limit
ai-topic-guard
allowed-hours
api-authentication
api-based-quota
api-based-throttling
base64-auth
basic-auth
business-rule
cache
content-filter
digest-auth
ip-black
ip-white
json-schema-validation
jwt-auth
max-message-size
message-builder
min-message-size
oauth-2-auth
oidc-auth
policy-client-banner
policy-decryption
policy-digital-sign
policy-digital-sign-verification
policy-encryption
policy-endpoint-rate-limit
policy-jose-implementation
policy-jose-validation
policy-json-transformation
policy-log
policy-mtls-authentication
policy-ws-security-decrypt
policy-ws-security-encrypt
policy-ws-security-from-target
policy-ws-security-sign
policy-ws-security-sign-validation
policy-ws-security-sts-token
policy-ws-security-timestamp
policy-ws-security-to-target
policy-ws-security-username
policy-xml-transformation
protocol-transformation-request
protocol-transformation-response
redaction
rest-api-call
saml-validation
script
xml-schema-validation
policy-group also exists as a _class discriminator but must not be used here — a policy group
is a distinct APIops resource, see Create Policy Group.
Response
Success Response (200 OK)
{
"status": "SUCCESS",
"resultList": [
{
"id": "665f2a1c9b3e4a0012ab34ce",
"name": "backend-ws-security",
"policyType": "policy-ws-security-username",
"policyTypeLabel": "policy-ws-security-username"
}
],
"resultCount": 1
}
Response Fields
| Field | Type | Description |
|---|---|---|
| status | string | Response status: SUCCESS or FAILURE |
| resultList | array | Single-element list containing the created policy's descriptor |
| resultCount | integer | Always 1 on success |
The response does not echo the saved policy body — use Get Global Policy to confirm it exists (it too only returns the lightweight descriptor, never the full body).
Error Response (400 Bad Request)
{
"status": "FAILURE",
"resultMessage": "name value can not be empty!"
}
or
{
"status": "FAILURE",
"resultMessage": "Policy snapshot could not be parsed."
}
Error Response (401 Unauthorized)
{
"status": "FAILURE",
"resultMessage": "Token is not valid!"
}
cURL Example
curl -X POST \
"https://demo.apinizer.com/apiops/projects/MyProject/globalPolicies/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"_class": "policy-ws-security-username",
"name": "backend-ws-security",
"description": "Username token injected before the request reaches the backend",
"active": true,
"username": "backend-service",
"password": "s3cr3t-already-encrypted-value-from-source-instance",
"passwordType": "PasswordText",
"mustUnderstand": true
}'
Notes and Warnings
- Always Creates: Unlike some other APIops write endpoints, this is create-only — it does not
upsert. Creating with a
namethat already exists in the project produces a second, separate record (name uniqueness is not enforced by this endpoint). - Cross-Instance Snapshot Semantics: Designed for cross-instance API Promotion;
@SecretDatafields are persisted exactly as received (assumed already encrypted). See Secret Contract above. policy-groupNot Supported Here: Use Policy Groups API for policy groups.- Permission: Requires
API_MANAGEMENT+MANAGEin the project.
Related Documentation
- Update Global Policy - Update an existing global policy (plaintext secret contract)
- Get Global Policy - Read a policy's descriptor back
- Delete Global Policy - Delete a global policy
- Global Policies API - Resource overview
- Authentication Guide - How to obtain and use API tokens
- Error Handling - Error response formats