diff --git a/api/v1alpha1/oauth2client_types.go b/api/v1alpha1/oauth2client_types.go
index 92efca9..36d468e 100644
--- a/api/v1alpha1/oauth2client_types.go
+++ b/api/v1alpha1/oauth2client_types.go
@@ -16,6 +16,7 @@ limitations under the License.
 package v1alpha1
 
 import (
+	"encoding/json"
 	"fmt"
 
 	"github.com/ory/hydra-maester/hydra"
@@ -106,8 +107,11 @@ type OAuth2ClientSpec struct {
 
 	// +kubebuilder:validation:Enum=;client_secret_basic;client_secret_post;private_key_jwt;none
 	//
-	// Indication which authenticaiton method shoud be used for the token endpoint
+	// Indication which authentication method shoud be used for the token endpoint
 	TokenEndpointAuthMethod TokenEndpointAuthMethod `json:"tokenEndpointAuthMethod,omitempty"`
+
+	// Metadata is abritrary data
+	Metadata json.RawMessage `json:"metadata,omitempty"`
 }
 
 // +kubebuilder:validation:Enum=client_credentials;authorization_code;implicit;refresh_token
@@ -123,7 +127,7 @@ type ResponseType string
 type RedirectURI string
 
 // +kubebuilder:validation:Enum=;client_secret_basic;client_secret_post;private_key_jwt;none
-// TokenEndpointAuthMethod represents an authenticaiton method for token endpoint
+// TokenEndpointAuthMethod represents an authentication method for token endpoint
 type TokenEndpointAuthMethod string
 
 // OAuth2ClientStatus defines the observed state of OAuth2Client
@@ -176,6 +180,7 @@ func (c *OAuth2Client) ToOAuth2ClientJSON() *hydra.OAuth2ClientJSON {
 		Scope:                   c.Spec.Scope,
 		Owner:                   fmt.Sprintf("%s/%s", c.Name, c.Namespace),
 		TokenEndpointAuthMethod: string(c.Spec.TokenEndpointAuthMethod),
+		Metadata:                c.Spec.Metadata,
 	}
 }
 
diff --git a/config/crd/bases/hydra.ory.sh_oauth2clients.yaml b/config/crd/bases/hydra.ory.sh_oauth2clients.yaml
index 144f312..697c623 100644
--- a/config/crd/bases/hydra.ory.sh_oauth2clients.yaml
+++ b/config/crd/bases/hydra.ory.sh_oauth2clients.yaml
@@ -455,13 +455,16 @@ spec:
               minItems: 1
               type: array
             tokenEndpointAuthMethod:
-              description: Indication which authenticaiton method shoud be used for the token endpoint.
+              description: Indication which authentication method shoud be used for the token endpoint.
               type: string
               enum:
               - client_secret_basic
               - client_secret_post
               - private_key_jwt
               - none
+            metadata:
+              description: Metadata is arbitrary data. This JSON will be stored into client and can be used to hold custom properties
+              type: object
             scope:
               description: Scope is a string containing a space-separated list of
                 scope values (as described in Section 3.3 of OAuth 2.0 [RFC6749])
diff --git a/config/samples/hydra_v1alpha1_oauth2client.yaml b/config/samples/hydra_v1alpha1_oauth2client.yaml
index a53eb99..750eade 100644
--- a/config/samples/hydra_v1alpha1_oauth2client.yaml
+++ b/config/samples/hydra_v1alpha1_oauth2client.yaml
@@ -30,4 +30,7 @@ spec:
     endpoint: /clients
     forwardedProto: https
   tokenEndpointAuthMethod: client_secret_basic
+  metadata:
+    property1: 1
+    property2: "2"
   
diff --git a/config/samples/hydra_v1alpha1_oauth2client_user_credentials.yaml b/config/samples/hydra_v1alpha1_oauth2client_user_credentials.yaml
index 6fc6a00..008e364 100644
--- a/config/samples/hydra_v1alpha1_oauth2client_user_credentials.yaml
+++ b/config/samples/hydra_v1alpha1_oauth2client_user_credentials.yaml
@@ -40,3 +40,6 @@ spec:
     endpoint: /clients
     forwardedProto: https
   tokenEndpointAuthMethod: client_secret_basic
+  metadata:
+    property1: 1
+    property2: "2"
diff --git a/hydra/client_test.go b/hydra/client_test.go
index 606eb69..15e99f6 100644
--- a/hydra/client_test.go
+++ b/hydra/client_test.go
@@ -21,12 +21,13 @@ const (
 	clientsEndpoint = "/clients"
 	schemeHTTP      = "http"
 
-	testID            = "test-id"
-	testClient        = `{"client_id":"test-id","owner":"test-name","scope":"some,scopes","grant_types":["type1"],"token_endpoint_auth_method":"client_secret_basic"}`
-	testClientCreated = `{"client_id":"test-id-2","client_secret":"TmGkvcY7k526","owner":"test-name-2","scope":"some,other,scopes","grant_types":["type2"],"audience":["audience-a","audience-b"],"token_endpoint_auth_method":"client_secret_basic"}`
-	testClientUpdated = `{"client_id":"test-id-3","client_secret":"xFoPPm654por","owner":"test-name-3","scope":"yet,another,scope","grant_types":["type3"],"audience":["audience-c"],"token_endpoint_auth_method":"client_secret_basic"}`
-	testClientList    = `{"client_id":"test-id-4","owner":"test-name-4","scope":"scope1 scope2","grant_types":["type4"],"token_endpoint_auth_method":"client_secret_basic"}`
-	testClientList2   = `{"client_id":"test-id-5","owner":"test-name-5","scope":"scope3 scope4","grant_types":["type5"],"token_endpoint_auth_method":"client_secret_basic"}`
+	testID                        = "test-id"
+	testClient                    = `{"client_id":"test-id","owner":"test-name","scope":"some,scopes","grant_types":["type1"],"token_endpoint_auth_method":"client_secret_basic"}`
+	testClientCreated             = `{"client_id":"test-id-2","client_secret":"TmGkvcY7k526","owner":"test-name-2","scope":"some,other,scopes","grant_types":["type2"],"audience":["audience-a","audience-b"],"token_endpoint_auth_method":"client_secret_basic"}`
+	testClientUpdated             = `{"client_id":"test-id-3","client_secret":"xFoPPm654por","owner":"test-name-3","scope":"yet,another,scope","grant_types":["type3"],"audience":["audience-c"],"token_endpoint_auth_method":"client_secret_basic"}`
+	testClientList                = `{"client_id":"test-id-4","owner":"test-name-4","scope":"scope1 scope2","grant_types":["type4"],"token_endpoint_auth_method":"client_secret_basic"}`
+	testClientList2               = `{"client_id":"test-id-5","owner":"test-name-5","scope":"scope3 scope4","grant_types":["type5"],"token_endpoint_auth_method":"client_secret_basic"}`
+	testClientWithMetadataCreated = `{"client_id":"test-id-21","client_secret":"TmGkvcY7k526","owner":"test-name-21","scope":"some,other,scopes","grant_types":["type2"],"token_endpoint_auth_method":"client_secret_basic","metadata":{"property1":1,"property2":"2"}}`
 
 	statusNotFoundBody            = `{"error":"Not Found","error_description":"Unable to locate the requested resource","status_code":404,"request_id":"id"}`
 	statusConflictBody            = `{"error":"Unable to insert or update resource because a resource with that value exists already","error_description":"","status_code":409,"request_id":"id"`
@@ -128,6 +129,11 @@ func TestCRUD(t *testing.T) {
 				testClientCreated,
 				nil,
 			},
+			"with new client with metadata": {
+				http.StatusCreated,
+				testClientWithMetadataCreated,
+				nil,
+			},
 			"with existing client": {
 				http.StatusConflict,
 				statusConflictBody,
@@ -140,9 +146,14 @@ func TestCRUD(t *testing.T) {
 			},
 		} {
 			t.Run(fmt.Sprintf("case/%s", d), func(t *testing.T) {
-
+				var (
+					err      error
+					o        *hydra.OAuth2ClientJSON
+					expected *hydra.OAuth2ClientJSON
+				)
 				//given
 				new := tc.statusCode == http.StatusCreated
+				newWithMetadata := d == "with new client with metadata"
 
 				h := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 					assert.Equal(c.HydraURL.String(), fmt.Sprintf("%s://%s%s", schemeHTTP, req.Host, req.URL.Path))
@@ -156,7 +167,23 @@ func TestCRUD(t *testing.T) {
 				runServer(&c, h)
 
 				//when
-				o, err := c.PostOAuth2Client(testOAuthJSONPost)
+				if newWithMetadata {
+					meta, _ := json.Marshal(map[string]interface{}{
+						"property1": float64(1),
+						"property2": "2",
+					})
+					var testOAuthJSONPost2 = &hydra.OAuth2ClientJSON{
+						Scope:      "some,other,scopes",
+						GrantTypes: []string{"type2"},
+						Owner:      "test-name-21",
+						Metadata:   meta,
+					}
+					o, err = c.PostOAuth2Client(testOAuthJSONPost2)
+					expected = testOAuthJSONPost2
+				} else {
+					o, err = c.PostOAuth2Client(testOAuthJSONPost)
+					expected = testOAuthJSONPost
+				}
 
 				//then
 				if tc.err == nil {
@@ -168,16 +195,24 @@ func TestCRUD(t *testing.T) {
 
 				if new {
 					require.NotNil(t, o)
-
-					assert.Equal(testOAuthJSONPost.Scope, o.Scope)
-					assert.Equal(testOAuthJSONPost.GrantTypes, o.GrantTypes)
-					assert.Equal(testOAuthJSONPost.Owner, o.Owner)
-					assert.Equal(testOAuthJSONPost.Audience, o.Audience)
+					assert.Equal(expected.Scope, o.Scope)
+					assert.Equal(expected.GrantTypes, o.GrantTypes)
+					assert.Equal(expected.Owner, o.Owner)
+					assert.Equal(expected.Audience, o.Audience)
 					assert.NotNil(o.Secret)
 					assert.NotNil(o.ClientID)
 					assert.NotNil(o.TokenEndpointAuthMethod)
-					if testOAuthJSONPost.TokenEndpointAuthMethod != "" {
-						assert.Equal(testOAuthJSONPost.TokenEndpointAuthMethod, o.TokenEndpointAuthMethod)
+					if expected.TokenEndpointAuthMethod != "" {
+						assert.Equal(expected.TokenEndpointAuthMethod, o.TokenEndpointAuthMethod)
+					}
+					if newWithMetadata {
+						assert.NotNil(o.Metadata)
+						assert.True(len(o.Metadata) > 0)
+						for key, _ := range o.Metadata {
+							assert.Equal(o.Metadata[key], expected.Metadata[key])
+						}
+					} else {
+						assert.Nil(o.Metadata)
 					}
 				}
 			})
diff --git a/hydra/types.go b/hydra/types.go
index 065d6f1..6248a17 100644
--- a/hydra/types.go
+++ b/hydra/types.go
@@ -1,18 +1,23 @@
 package hydra
 
-import "k8s.io/utils/pointer"
+import (
+	"encoding/json"
+
+	"k8s.io/utils/pointer"
+)
 
 // OAuth2ClientJSON represents an OAuth2 client digestible by ORY Hydra
 type OAuth2ClientJSON struct {
-	ClientID                *string  `json:"client_id,omitempty"`
-	Secret                  *string  `json:"client_secret,omitempty"`
-	GrantTypes              []string `json:"grant_types"`
-	RedirectURIs            []string `json:"redirect_uris,omitempty"`
-	ResponseTypes           []string `json:"response_types,omitempty"`
-	Audience                []string `json:"audience,omitempty"`
-	Scope                   string   `json:"scope"`
-	Owner                   string   `json:"owner"`
-	TokenEndpointAuthMethod string   `json:"token_endpoint_auth_method,omitempty"`
+	ClientID                *string         `json:"client_id,omitempty"`
+	Secret                  *string         `json:"client_secret,omitempty"`
+	GrantTypes              []string        `json:"grant_types"`
+	RedirectURIs            []string        `json:"redirect_uris,omitempty"`
+	ResponseTypes           []string        `json:"response_types,omitempty"`
+	Audience                []string        `json:"audience,omitempty"`
+	Scope                   string          `json:"scope"`
+	Owner                   string          `json:"owner"`
+	TokenEndpointAuthMethod string          `json:"token_endpoint_auth_method,omitempty"`
+	Metadata                json.RawMessage `json:"metadata,omitempty"`
 }
 
 // Oauth2ClientCredentials represents client ID and password fetched from a Kubernetes secret