diff --git a/.dbeaver/credentials-config.json b/.dbeaver/credentials-config.json
index 685527df0..e69de29bb 100644
--- a/.dbeaver/credentials-config.json
+++ b/.dbeaver/credentials-config.json
@@ -1,2 +0,0 @@
-�
-�_��?��e��B�K�~9!&Rf)v��
��`�
}^<��	&�a�-��w4�c1I�rԙ�d��ONX��[�Bf�Z�X��H�AOy�[c
\ No newline at end of file
diff --git a/.dbeaver/data-sources.json b/.dbeaver/data-sources.json
index e0ca3441f..bfeae8069 100644
--- a/.dbeaver/data-sources.json
+++ b/.dbeaver/data-sources.json
@@ -1,6 +1,7 @@
 {
 	"folders": {},
 	"connections": {
+<<<<<<< HEAD
 		"mariaDB-180637bab9c-385a8c5454123150": {
 			"provider": "mysql",
 			"driver": "mariaDB",
@@ -38,6 +39,22 @@
 						}
 					}
 				}
+=======
+		"mariaDB-1813fbbc7bc-107c0b3aeaeb91ab": {
+			"provider": "mysql",
+			"driver": "mariaDB",
+			"name": "gradido",
+			"save-password": true,
+			"read-only": false,
+			"configuration": {
+				"host": "localhost",
+				"port": "3306",
+				"url": "jdbc:mariadb://localhost:3306/",
+				"home": "mysql_client",
+				"type": "dev",
+				"auth-model": "native",
+				"handlers": {}
+>>>>>>> refs/remotes/origin/master
 			}
 		}
 	},
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index b7000100e..b935ef8f4 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -528,7 +528,7 @@ jobs:
           report_name: Coverage Backend
           type: lcov
           result_path: ./backend/coverage/lcov.info
-          min_coverage: 68
+          min_coverage: 70
           token: ${{ github.token }}
 
   ##########################################################################
diff --git a/.gitignore b/.gitignore
index ab879e79a..7ff1e202d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,10 @@
+<<<<<<< HEAD
 .dbeaver/*
 .project
+=======
+>>>>>>> refs/remotes/origin/master
 *.log
+*.bak
 /node_modules/*
 messages.pot
 nbproject
diff --git a/backend/.env.dist b/backend/.env.dist
index 62b786456..41eeeaf58 100644
--- a/backend/.env.dist
+++ b/backend/.env.dist
@@ -1,4 +1,4 @@
-CONFIG_VERSION=v6.2022-04-21
+CONFIG_VERSION=v7.2022-06-15
 
 # Server
 PORT=4000
@@ -28,6 +28,7 @@ COMMUNITY_NAME=Gradido Entwicklung
 COMMUNITY_URL=http://localhost/
 COMMUNITY_REGISTER_URL=http://localhost/register
 COMMUNITY_REDEEM_URL=http://localhost/redeem/{code}
+COMMUNITY_REDEEM_CONTRIBUTION_URL=http://localhost/redeem/CL-{code}
 COMMUNITY_DESCRIPTION=Die lokale Entwicklungsumgebung von Gradido.
 
 # Login Server
diff --git a/backend/.env.template b/backend/.env.template
index 140ec67e9..284abc204 100644
--- a/backend/.env.template
+++ b/backend/.env.template
@@ -27,6 +27,7 @@ COMMUNITY_NAME=$COMMUNITY_NAME
 COMMUNITY_URL=$COMMUNITY_URL
 COMMUNITY_REGISTER_URL=$COMMUNITY_REGISTER_URL
 COMMUNITY_REDEEM_URL=$COMMUNITY_REDEEM_URL
+COMMUNITY_REDEEM_CONTRIBUTION_URL=$COMMUNITY_REDEEM_CONTRIBUTION_URL
 COMMUNITY_DESCRIPTION=$COMMUNITY_DESCRIPTION
 
 # Login Server
diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts
index 8188b3daa..8ac2c78cc 100644
--- a/backend/src/auth/RIGHTS.ts
+++ b/backend/src/auth/RIGHTS.ts
@@ -37,4 +37,8 @@ export enum RIGHTS {
   UNDELETE_USER = 'UNDELETE_USER',
   CREATION_TRANSACTION_LIST = 'CREATION_TRANSACTION_LIST',
   LIST_TRANSACTION_LINKS_ADMIN = 'LIST_TRANSACTION_LINKS_ADMIN',
+  CREATE_CONTRIBUTION_LINK = 'CREATE_CONTRIBUTION_LINK',
+  LIST_CONTRIBUTION_LINKS = 'LIST_CONTRIBUTION_LINKS',
+  DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK',
+  UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK',
 }
diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts
index 28318ed6b..dafcd4bf0 100644
--- a/backend/src/config/index.ts
+++ b/backend/src/config/index.ts
@@ -10,14 +10,14 @@ Decimal.set({
 })
 
 const constants = {
-  DB_VERSION: '0036-unique_previous_in_transactions',
+  DB_VERSION: '0038-add_contribution_links_table',
   DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
   LOG4JS_CONFIG: 'log4js-config.json',
   // default log level on production should be info
   LOG_LEVEL: process.env.LOG_LEVEL || 'info',
   CONFIG_VERSION: {
     DEFAULT: 'DEFAULT',
-    EXPECTED: 'v6.2022-04-21',
+    EXPECTED: 'v7.2022-06-15',
     CURRENT: '',
   },
 }
@@ -54,6 +54,8 @@ const community = {
   COMMUNITY_URL: process.env.COMMUNITY_URL || 'http://localhost/',
   COMMUNITY_REGISTER_URL: process.env.COMMUNITY_REGISTER_URL || 'http://localhost/register',
   COMMUNITY_REDEEM_URL: process.env.COMMUNITY_REDEEM_URL || 'http://localhost/redeem/{code}',
+  COMMUNITY_REDEEM_CONTRIBUTION_URL:
+    process.env.COMMUNITY_REDEEM_CONTRIBUTION_URL || 'http://localhost/redeem/CL-{code}',
   COMMUNITY_DESCRIPTION:
     process.env.COMMUNITY_DESCRIPTION || 'Die lokale Entwicklungsumgebung von Gradido.',
 }
diff --git a/backend/src/graphql/arg/ContributionLinkArgs.ts b/backend/src/graphql/arg/ContributionLinkArgs.ts
new file mode 100644
index 000000000..7344a28ff
--- /dev/null
+++ b/backend/src/graphql/arg/ContributionLinkArgs.ts
@@ -0,0 +1,29 @@
+import { ArgsType, Field, Int } from 'type-graphql'
+import Decimal from 'decimal.js-light'
+
+@ArgsType()
+export default class ContributionLinkArgs {
+  @Field(() => Decimal)
+  amount: Decimal
+
+  @Field(() => String)
+  name: string
+
+  @Field(() => String)
+  memo: string
+
+  @Field(() => String)
+  cycle: string
+
+  @Field(() => String, { nullable: true })
+  validFrom?: string | null
+
+  @Field(() => String, { nullable: true })
+  validTo?: string | null
+
+  @Field(() => Decimal, { nullable: true })
+  maxAmountPerMonth: Decimal | null
+
+  @Field(() => Int)
+  maxPerCycle: number
+}
diff --git a/backend/src/graphql/enum/ContributionCycleType.ts b/backend/src/graphql/enum/ContributionCycleType.ts
new file mode 100644
index 000000000..5fe494a02
--- /dev/null
+++ b/backend/src/graphql/enum/ContributionCycleType.ts
@@ -0,0 +1,28 @@
+import { registerEnumType } from 'type-graphql'
+
+export enum ContributionCycleType {
+  ONCE = 'once',
+  HOUR = 'hour',
+  TWO_HOURS = 'two_hours',
+  FOUR_HOURS = 'four_hours',
+  EIGHT_HOURS = 'eight_hours',
+  HALF_DAY = 'half_day',
+  DAY = 'day',
+  TWO_DAYS = 'two_days',
+  THREE_DAYS = 'three_days',
+  FOUR_DAYS = 'four_days',
+  FIVE_DAYS = 'five_days',
+  SIX_DAYS = 'six_days',
+  WEEK = 'week',
+  TWO_WEEKS = 'two_weeks',
+  MONTH = 'month',
+  TWO_MONTH = 'two_month',
+  QUARTER = 'quarter',
+  HALF_YEAR = 'half_year',
+  YEAR = 'year',
+}
+
+registerEnumType(ContributionCycleType, {
+  name: 'ContributionCycleType', // this one is mandatory
+  description: 'Name of the Type of the ContributionCycle', // this one is optional
+})
diff --git a/backend/src/graphql/model/ContributionLink.ts b/backend/src/graphql/model/ContributionLink.ts
new file mode 100644
index 000000000..9fe9eccd6
--- /dev/null
+++ b/backend/src/graphql/model/ContributionLink.ts
@@ -0,0 +1,62 @@
+import { ObjectType, Field, Int } from 'type-graphql'
+import Decimal from 'decimal.js-light'
+import { ContributionLink as dbContributionLink } from '@entity/ContributionLink'
+import CONFIG from '@/config'
+
+@ObjectType()
+export class ContributionLink {
+  constructor(contributionLink: dbContributionLink) {
+    this.id = contributionLink.id
+    this.amount = contributionLink.amount
+    this.name = contributionLink.name
+    this.memo = contributionLink.memo
+    this.createdAt = contributionLink.createdAt
+    this.deletedAt = contributionLink.deletedAt
+    this.validFrom = contributionLink.validFrom
+    this.validTo = contributionLink.validTo
+    this.maxAmountPerMonth = contributionLink.maxAmountPerMonth
+    this.cycle = contributionLink.cycle
+    this.maxPerCycle = contributionLink.maxPerCycle
+    this.code = contributionLink.code
+    this.link = CONFIG.COMMUNITY_REDEEM_CONTRIBUTION_URL.replace(/{code}/g, this.code)
+  }
+
+  @Field(() => Number)
+  id: number
+
+  @Field(() => Decimal)
+  amount: Decimal
+
+  @Field(() => String)
+  name: string
+
+  @Field(() => String)
+  memo: string
+
+  @Field(() => String)
+  code: string
+
+  @Field(() => String)
+  link: string
+
+  @Field(() => Date)
+  createdAt: Date
+
+  @Field(() => Date, { nullable: true })
+  deletedAt: Date | null
+
+  @Field(() => Date, { nullable: true })
+  validFrom: Date | null
+
+  @Field(() => Date, { nullable: true })
+  validTo: Date | null
+
+  @Field(() => Decimal, { nullable: true })
+  maxAmountPerMonth: Decimal | null
+
+  @Field(() => String)
+  cycle: string
+
+  @Field(() => Int)
+  maxPerCycle: number
+}
diff --git a/backend/src/graphql/model/ContributionLinkList.ts b/backend/src/graphql/model/ContributionLinkList.ts
new file mode 100644
index 000000000..412d0bf7b
--- /dev/null
+++ b/backend/src/graphql/model/ContributionLinkList.ts
@@ -0,0 +1,11 @@
+import { ObjectType, Field } from 'type-graphql'
+import { ContributionLink } from '@model/ContributionLink'
+
+@ObjectType()
+export class ContributionLinkList {
+  @Field(() => [ContributionLink])
+  links: ContributionLink[]
+
+  @Field(() => Number)
+  count: number
+}
diff --git a/backend/src/graphql/resolver/AdminResolver.test.ts b/backend/src/graphql/resolver/AdminResolver.test.ts
index acf880efb..7417b529e 100644
--- a/backend/src/graphql/resolver/AdminResolver.test.ts
+++ b/backend/src/graphql/resolver/AdminResolver.test.ts
@@ -20,12 +20,16 @@ import {
   updatePendingCreation,
   deletePendingCreation,
   confirmPendingCreation,
+  createContributionLink,
+  deleteContributionLink,
+  updateContributionLink,
 } from '@/seeds/graphql/mutations'
 import {
   getPendingCreations,
   login,
   searchUsers,
   listTransactionLinksAdmin,
+  listContributionLinks,
 } from '@/seeds/graphql/queries'
 import { GraphQLError } from 'graphql'
 import { User } from '@entity/User'
@@ -34,6 +38,7 @@ import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail'
 import Decimal from 'decimal.js-light'
 import { AdminPendingCreation } from '@entity/AdminPendingCreation'
 import { Transaction as DbTransaction } from '@entity/Transaction'
+import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
 
 // mock account activation email to avoid console spam
 jest.mock('@/mailer/sendAccountActivationEmail', () => {
@@ -1593,4 +1598,361 @@ describe('AdminResolver', () => {
       })
     })
   })
+
+  describe('Contribution Links', () => {
+    const variables = {
+      amount: new Decimal(200),
+      name: 'Dokumenta 2022',
+      memo: 'Danke für deine Teilnahme an der Dokumenta 2022',
+      cycle: 'once',
+      validFrom: new Date(2022, 5, 18).toISOString(),
+      validTo: new Date(2022, 7, 14).toISOString(),
+      maxAmountPerMonth: new Decimal(200),
+      maxPerCycle: 1,
+    }
+
+    describe('unauthenticated', () => {
+      describe('createContributionLink', () => {
+        it('returns an error', async () => {
+          await expect(mutate({ mutation: createContributionLink, variables })).resolves.toEqual(
+            expect.objectContaining({
+              errors: [new GraphQLError('401 Unauthorized')],
+            }),
+          )
+        })
+      })
+
+      describe('listContributionLinks', () => {
+        it('returns an error', async () => {
+          await expect(query({ query: listContributionLinks })).resolves.toEqual(
+            expect.objectContaining({
+              errors: [new GraphQLError('401 Unauthorized')],
+            }),
+          )
+        })
+      })
+
+      describe('updateContributionLink', () => {
+        it('returns an error', async () => {
+          await expect(
+            mutate({
+              mutation: updateContributionLink,
+              variables: {
+                ...variables,
+                id: -1,
+                amount: new Decimal(400),
+                name: 'Dokumenta 2023',
+                memo: 'Danke für deine Teilnahme an der Dokumenta 2023',
+              },
+            }),
+          ).resolves.toEqual(
+            expect.objectContaining({
+              errors: [new GraphQLError('401 Unauthorized')],
+            }),
+          )
+        })
+      })
+
+      describe('deleteContributionLink', () => {
+        it('returns an error', async () => {
+          await expect(
+            mutate({ mutation: deleteContributionLink, variables: { id: -1 } }),
+          ).resolves.toEqual(
+            expect.objectContaining({
+              errors: [new GraphQLError('401 Unauthorized')],
+            }),
+          )
+        })
+      })
+    })
+
+    describe('authenticated', () => {
+      describe('without admin rights', () => {
+        beforeAll(async () => {
+          user = await userFactory(testEnv, bibiBloxberg)
+          await query({
+            query: login,
+            variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
+          })
+        })
+
+        afterAll(async () => {
+          await cleanDB()
+          resetToken()
+        })
+
+        describe('createContributionLink', () => {
+          it('returns an error', async () => {
+            await expect(mutate({ mutation: createContributionLink, variables })).resolves.toEqual(
+              expect.objectContaining({
+                errors: [new GraphQLError('401 Unauthorized')],
+              }),
+            )
+          })
+        })
+
+        describe('listContributionLinks', () => {
+          it('returns an error', async () => {
+            await expect(query({ query: listContributionLinks })).resolves.toEqual(
+              expect.objectContaining({
+                errors: [new GraphQLError('401 Unauthorized')],
+              }),
+            )
+          })
+        })
+
+        describe('updateContributionLink', () => {
+          it('returns an error', async () => {
+            await expect(
+              mutate({
+                mutation: updateContributionLink,
+                variables: {
+                  ...variables,
+                  id: -1,
+                  amount: new Decimal(400),
+                  name: 'Dokumenta 2023',
+                  memo: 'Danke für deine Teilnahme an der Dokumenta 2023',
+                },
+              }),
+            ).resolves.toEqual(
+              expect.objectContaining({
+                errors: [new GraphQLError('401 Unauthorized')],
+              }),
+            )
+          })
+        })
+
+        describe('deleteContributionLink', () => {
+          it('returns an error', async () => {
+            await expect(
+              mutate({ mutation: deleteContributionLink, variables: { id: -1 } }),
+            ).resolves.toEqual(
+              expect.objectContaining({
+                errors: [new GraphQLError('401 Unauthorized')],
+              }),
+            )
+          })
+        })
+      })
+
+      describe('with admin rights', () => {
+        beforeAll(async () => {
+          user = await userFactory(testEnv, peterLustig)
+          await query({
+            query: login,
+            variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
+          })
+        })
+
+        afterAll(async () => {
+          await cleanDB()
+          resetToken()
+        })
+
+        describe('createContributionLink', () => {
+          it('returns a contribution link object', async () => {
+            await expect(mutate({ mutation: createContributionLink, variables })).resolves.toEqual(
+              expect.objectContaining({
+                data: {
+                  createContributionLink: expect.objectContaining({
+                    id: expect.any(Number),
+                    amount: '200',
+                    code: expect.stringMatching(/^[0-9a-f]{24,24}$/),
+                    link: expect.stringMatching(/^.*?\/CL-[0-9a-f]{24,24}$/),
+                    createdAt: expect.any(String),
+                    name: 'Dokumenta 2022',
+                    memo: 'Danke für deine Teilnahme an der Dokumenta 2022',
+                    validFrom: expect.any(String),
+                    validTo: expect.any(String),
+                    maxAmountPerMonth: '200',
+                    cycle: 'once',
+                    maxPerCycle: 1,
+                  }),
+                },
+              }),
+            )
+          })
+
+          it('has a contribution link stored in db', async () => {
+            const cls = await DbContributionLink.find()
+            expect(cls).toHaveLength(1)
+            expect(cls[0]).toEqual(
+              expect.objectContaining({
+                id: expect.any(Number),
+                name: 'Dokumenta 2022',
+                memo: 'Danke für deine Teilnahme an der Dokumenta 2022',
+                validFrom: new Date('2022-06-18T00:00:00.000Z'),
+                validTo: new Date('2022-08-14T00:00:00.000Z'),
+                cycle: 'once',
+                maxPerCycle: 1,
+                totalMaxCountOfContribution: null,
+                maxAccountBalance: null,
+                minGapHours: null,
+                createdAt: expect.any(Date),
+                deletedAt: null,
+                code: expect.stringMatching(/^[0-9a-f]{24,24}$/),
+                linkEnabled: true,
+                // amount: '200',
+                // maxAmountPerMonth: '200',
+              }),
+            )
+          })
+        })
+
+        describe('listContributionLinks', () => {
+          describe('one link in DB', () => {
+            it('returns the link and count 1', async () => {
+              await expect(query({ query: listContributionLinks })).resolves.toEqual(
+                expect.objectContaining({
+                  data: {
+                    listContributionLinks: {
+                      links: expect.arrayContaining([
+                        expect.objectContaining({
+                          amount: '200',
+                          code: expect.stringMatching(/^[0-9a-f]{24,24}$/),
+                          link: expect.stringMatching(/^.*?\/CL-[0-9a-f]{24,24}$/),
+                          createdAt: expect.any(String),
+                          name: 'Dokumenta 2022',
+                          memo: 'Danke für deine Teilnahme an der Dokumenta 2022',
+                          validFrom: expect.any(String),
+                          validTo: expect.any(String),
+                          maxAmountPerMonth: '200',
+                          cycle: 'once',
+                          maxPerCycle: 1,
+                        }),
+                      ]),
+                      count: 1,
+                    },
+                  },
+                }),
+              )
+            })
+          })
+        })
+
+        describe('updateContributionLink', () => {
+          describe('no valid id', () => {
+            it('returns an error', async () => {
+              await expect(
+                mutate({
+                  mutation: updateContributionLink,
+                  variables: {
+                    ...variables,
+                    id: -1,
+                    amount: new Decimal(400),
+                    name: 'Dokumenta 2023',
+                    memo: 'Danke für deine Teilnahme an der Dokumenta 2023',
+                  },
+                }),
+              ).resolves.toEqual(
+                expect.objectContaining({
+                  errors: [new GraphQLError('Contribution Link not found to given id.')],
+                }),
+              )
+            })
+          })
+
+          describe('valid id', () => {
+            let linkId: number
+            beforeAll(async () => {
+              const links = await query({ query: listContributionLinks })
+              linkId = links.data.listContributionLinks.links[0].id
+            })
+
+            it('returns updated contribution link object', async () => {
+              await expect(
+                mutate({
+                  mutation: updateContributionLink,
+                  variables: {
+                    ...variables,
+                    id: linkId,
+                    amount: new Decimal(400),
+                    name: 'Dokumenta 2023',
+                    memo: 'Danke für deine Teilnahme an der Dokumenta 2023',
+                  },
+                }),
+              ).resolves.toEqual(
+                expect.objectContaining({
+                  data: {
+                    updateContributionLink: {
+                      id: linkId,
+                      amount: '400',
+                      code: expect.stringMatching(/^[0-9a-f]{24,24}$/),
+                      link: expect.stringMatching(/^.*?\/CL-[0-9a-f]{24,24}$/),
+                      createdAt: expect.any(String),
+                      name: 'Dokumenta 2023',
+                      memo: 'Danke für deine Teilnahme an der Dokumenta 2023',
+                      validFrom: expect.any(String),
+                      validTo: expect.any(String),
+                      maxAmountPerMonth: '200',
+                      cycle: 'once',
+                      maxPerCycle: 1,
+                    },
+                  },
+                }),
+              )
+            })
+
+            it('updated the DB record', async () => {
+              await expect(DbContributionLink.findOne(linkId)).resolves.toEqual(
+                expect.objectContaining({
+                  id: linkId,
+                  name: 'Dokumenta 2023',
+                  memo: 'Danke für deine Teilnahme an der Dokumenta 2023',
+                  // amount: '400',
+                }),
+              )
+            })
+          })
+        })
+
+        describe('deleteContributionLink', () => {
+          describe('no valid id', () => {
+            it('returns an error', async () => {
+              await expect(
+                mutate({ mutation: deleteContributionLink, variables: { id: -1 } }),
+              ).resolves.toEqual(
+                expect.objectContaining({
+                  errors: [new GraphQLError('Contribution Link not found to given id.')],
+                }),
+              )
+            })
+          })
+
+          describe('valid id', () => {
+            let linkId: number
+            beforeAll(async () => {
+              const links = await query({ query: listContributionLinks })
+              linkId = links.data.listContributionLinks.links[0].id
+            })
+
+            it('returns a date string', async () => {
+              await expect(
+                mutate({ mutation: deleteContributionLink, variables: { id: linkId } }),
+              ).resolves.toEqual(
+                expect.objectContaining({
+                  data: {
+                    deleteContributionLink: expect.any(String),
+                  },
+                }),
+              )
+            })
+
+            it('does not list this contribution link anymore', async () => {
+              await expect(query({ query: listContributionLinks })).resolves.toEqual(
+                expect.objectContaining({
+                  data: {
+                    listContributionLinks: {
+                      links: [],
+                      count: 0,
+                    },
+                  },
+                }),
+              )
+            })
+          })
+        })
+      })
+    })
+  })
 })
diff --git a/backend/src/graphql/resolver/AdminResolver.ts b/backend/src/graphql/resolver/AdminResolver.ts
index 4c94e48c8..785a7de02 100644
--- a/backend/src/graphql/resolver/AdminResolver.ts
+++ b/backend/src/graphql/resolver/AdminResolver.ts
@@ -1,4 +1,5 @@
 import { Context, getUser } from '@/server/context'
+import { backendLogger as logger } from '@/server/logger'
 import { Resolver, Query, Arg, Args, Authorized, Mutation, Ctx, Int } from 'type-graphql'
 import {
   getCustomRepository,
@@ -14,12 +15,16 @@ import { UserAdmin, SearchUsersResult } from '@model/UserAdmin'
 import { PendingCreation } from '@model/PendingCreation'
 import { CreatePendingCreations } from '@model/CreatePendingCreations'
 import { UpdatePendingCreation } from '@model/UpdatePendingCreation'
+import { ContributionLink } from '@model/ContributionLink'
+import { ContributionLinkList } from '@model/ContributionLinkList'
 import { RIGHTS } from '@/auth/RIGHTS'
 import { UserRepository } from '@repository/User'
 import CreatePendingCreationArgs from '@arg/CreatePendingCreationArgs'
 import UpdatePendingCreationArgs from '@arg/UpdatePendingCreationArgs'
 import SearchUsersArgs from '@arg/SearchUsersArgs'
+import ContributionLinkArgs from '@arg/ContributionLinkArgs'
 import { Transaction as DbTransaction } from '@entity/Transaction'
+import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
 import { Transaction } from '@model/Transaction'
 import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink'
 import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
@@ -39,6 +44,7 @@ import { Order } from '@enum/Order'
 import { communityUser } from '@/util/communityUser'
 import { checkOptInCode, activationLink, printTimeDuration } from './UserResolver'
 import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail'
+import { transactionLinkCode as contributionLinkCode } from './TransactionLinkResolver'
 import CONFIG from '@/config'
 
 // const EMAIL_OPT_IN_REGISTER = 1
@@ -460,6 +466,99 @@ export class AdminResolver {
       linkList: transactionLinks.map((tl) => new TransactionLink(tl, new User(user))),
     }
   }
+
+  @Authorized([RIGHTS.CREATE_CONTRIBUTION_LINK])
+  @Mutation(() => ContributionLink)
+  async createContributionLink(
+    @Args()
+    {
+      amount,
+      name,
+      memo,
+      cycle,
+      validFrom,
+      validTo,
+      maxAmountPerMonth,
+      maxPerCycle,
+    }: ContributionLinkArgs,
+  ): Promise<ContributionLink> {
+    const dbContributionLink = new DbContributionLink()
+    dbContributionLink.amount = amount
+    dbContributionLink.name = name
+    dbContributionLink.memo = memo
+    dbContributionLink.createdAt = new Date()
+    dbContributionLink.code = contributionLinkCode(dbContributionLink.createdAt)
+    dbContributionLink.cycle = cycle
+    if (validFrom) dbContributionLink.validFrom = new Date(validFrom)
+    if (validTo) dbContributionLink.validTo = new Date(validTo)
+    dbContributionLink.maxAmountPerMonth = maxAmountPerMonth
+    dbContributionLink.maxPerCycle = maxPerCycle
+    await dbContributionLink.save()
+    return new ContributionLink(dbContributionLink)
+  }
+
+  @Authorized([RIGHTS.LIST_CONTRIBUTION_LINKS])
+  @Query(() => ContributionLinkList)
+  async listContributionLinks(
+    @Args()
+    { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
+  ): Promise<ContributionLinkList> {
+    const [links, count] = await DbContributionLink.findAndCount({
+      order: { createdAt: order },
+      skip: (currentPage - 1) * pageSize,
+      take: pageSize,
+    })
+    return {
+      links: links.map((link: DbContributionLink) => new ContributionLink(link)),
+      count,
+    }
+  }
+
+  @Authorized([RIGHTS.DELETE_CONTRIBUTION_LINK])
+  @Mutation(() => Date, { nullable: true })
+  async deleteContributionLink(@Arg('id', () => Int) id: number): Promise<Date | null> {
+    const contributionLink = await DbContributionLink.findOne(id)
+    if (!contributionLink) {
+      logger.error(`Contribution Link not found to given id: ${id}`)
+      throw new Error('Contribution Link not found to given id.')
+    }
+    await contributionLink.softRemove()
+    const newContributionLink = await DbContributionLink.findOne({ id }, { withDeleted: true })
+    return newContributionLink ? newContributionLink.deletedAt : null
+  }
+
+  @Authorized([RIGHTS.UPDATE_CONTRIBUTION_LINK])
+  @Mutation(() => ContributionLink)
+  async updateContributionLink(
+    @Args()
+    {
+      amount,
+      name,
+      memo,
+      cycle,
+      validFrom,
+      validTo,
+      maxAmountPerMonth,
+      maxPerCycle,
+    }: ContributionLinkArgs,
+    @Arg('id', () => Int) id: number,
+  ): Promise<ContributionLink> {
+    const dbContributionLink = await DbContributionLink.findOne(id)
+    if (!dbContributionLink) {
+      logger.error(`Contribution Link not found to given id: ${id}`)
+      throw new Error('Contribution Link not found to given id.')
+    }
+    dbContributionLink.amount = amount
+    dbContributionLink.name = name
+    dbContributionLink.memo = memo
+    dbContributionLink.cycle = cycle
+    if (validFrom) dbContributionLink.validFrom = new Date(validFrom)
+    if (validTo) dbContributionLink.validTo = new Date(validTo)
+    dbContributionLink.maxAmountPerMonth = maxAmountPerMonth
+    dbContributionLink.maxPerCycle = maxPerCycle
+    await dbContributionLink.save()
+    return new ContributionLink(dbContributionLink)
+  }
 }
 
 interface CreationMap {
diff --git a/backend/src/seeds/contributionLink/ContributionLinkInterface.ts b/backend/src/seeds/contributionLink/ContributionLinkInterface.ts
new file mode 100644
index 000000000..15ba4b72d
--- /dev/null
+++ b/backend/src/seeds/contributionLink/ContributionLinkInterface.ts
@@ -0,0 +1,7 @@
+export interface ContributionLinkInterface {
+  amount: number
+  name: string
+  memo: string
+  validFrom?: Date
+  validTo?: Date
+}
diff --git a/backend/src/seeds/contributionLink/index.ts b/backend/src/seeds/contributionLink/index.ts
new file mode 100644
index 000000000..41d28eb60
--- /dev/null
+++ b/backend/src/seeds/contributionLink/index.ts
@@ -0,0 +1,18 @@
+import { ContributionLinkInterface } from './ContributionLinkInterface'
+
+export const contributionLinks: ContributionLinkInterface[] = [
+  {
+    name: 'Dokumenta 2017',
+    memo: 'Vielen Dank für deinen Besuch bei der Dokumenta 2017',
+    amount: 200,
+    validFrom: new Date(2017, 3, 8),
+    validTo: new Date(2017, 6, 16),
+  },
+  {
+    name: 'Dokumenta 2022',
+    memo: 'Vielen Dank für deinen Besuch bei der Dokumenta 2022',
+    amount: 200,
+    validFrom: new Date(2022, 5, 18),
+    validTo: new Date(2022, 8, 25),
+  },
+]
diff --git a/backend/src/seeds/factory/contributionLink.ts b/backend/src/seeds/factory/contributionLink.ts
new file mode 100644
index 000000000..7e34b9d20
--- /dev/null
+++ b/backend/src/seeds/factory/contributionLink.ts
@@ -0,0 +1,27 @@
+import { ApolloServerTestClient } from 'apollo-server-testing'
+import { createContributionLink } from '@/seeds/graphql/mutations'
+import { login } from '@/seeds/graphql/queries'
+import { ContributionLinkInterface } from '@/seeds/contributionLink/ContributionLinkInterface'
+
+export const contributionLinkFactory = async (
+  client: ApolloServerTestClient,
+  contributionLink: ContributionLinkInterface,
+): Promise<void> => {
+  const { mutate, query } = client
+
+  // login as admin
+  await query({ query: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } })
+
+  const variables = {
+    amount: contributionLink.amount,
+    memo: contributionLink.memo,
+    name: contributionLink.name,
+    cycle: 'ONCE',
+    maxPerCycle: 1,
+    maxAmountPerMonth: 200,
+    validFrom: contributionLink.validFrom ? contributionLink.validFrom.toISOString() : undefined,
+    validTo: contributionLink.validTo ? contributionLink.validTo.toISOString() : undefined,
+  }
+
+  await mutate({ mutation: createContributionLink, variables })
+}
diff --git a/backend/src/seeds/graphql/mutations.ts b/backend/src/seeds/graphql/mutations.ts
index e66827566..253f78e2a 100644
--- a/backend/src/seeds/graphql/mutations.ts
+++ b/backend/src/seeds/graphql/mutations.ts
@@ -137,3 +137,85 @@ export const deletePendingCreation = gql`
     deletePendingCreation(id: $id)
   }
 `
+
+export const createContributionLink = gql`
+  mutation (
+    $amount: Decimal!
+    $name: String!
+    $memo: String!
+    $cycle: String!
+    $validFrom: String
+    $validTo: String
+    $maxAmountPerMonth: Decimal
+    $maxPerCycle: Int! = 1
+  ) {
+    createContributionLink(
+      amount: $amount
+      name: $name
+      memo: $memo
+      cycle: $cycle
+      validFrom: $validFrom
+      validTo: $validTo
+      maxAmountPerMonth: $maxAmountPerMonth
+      maxPerCycle: $maxPerCycle
+    ) {
+      id
+      amount
+      name
+      memo
+      code
+      link
+      createdAt
+      validFrom
+      validTo
+      maxAmountPerMonth
+      cycle
+      maxPerCycle
+    }
+  }
+`
+
+export const updateContributionLink = gql`
+  mutation (
+    $amount: Decimal!
+    $name: String!
+    $memo: String!
+    $cycle: String!
+    $validFrom: String
+    $validTo: String
+    $maxAmountPerMonth: Decimal
+    $maxPerCycle: Int! = 1
+    $id: Int!
+  ) {
+    updateContributionLink(
+      amount: $amount
+      name: $name
+      memo: $memo
+      cycle: $cycle
+      validFrom: $validFrom
+      validTo: $validTo
+      maxAmountPerMonth: $maxAmountPerMonth
+      maxPerCycle: $maxPerCycle
+      id: $id
+    ) {
+      id
+      amount
+      name
+      memo
+      code
+      link
+      createdAt
+      validFrom
+      validTo
+      maxAmountPerMonth
+      cycle
+      maxPerCycle
+    }
+  }
+`
+
+export const deleteContributionLink = gql`
+  mutation ($id: Int!) {
+    deleteContributionLink(id: $id)
+  }
+`
diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts
index 03ee3b53e..9a0e00be3 100644
--- a/backend/src/seeds/graphql/queries.ts
+++ b/backend/src/seeds/graphql/queries.ts
@@ -217,3 +217,25 @@ export const listTransactionLinksAdmin = gql`
     }
   }
 `
+
+export const listContributionLinks = gql`
+  query ($pageSize: Int = 25, $currentPage: Int = 1, $order: Order) {
+    listContributionLinks(pageSize: $pageSize, currentPage: $currentPage, order: $order) {
+      links {
+        id
+        amount
+        name
+        memo
+        code
+        link
+        createdAt
+        validFrom
+        validTo
+        maxAmountPerMonth
+        cycle
+        maxPerCycle
+      }
+      count
+    }
+  }
+`
diff --git a/backend/src/seeds/index.ts b/backend/src/seeds/index.ts
index 710f255ee..8e9a4e2d8 100644
--- a/backend/src/seeds/index.ts
+++ b/backend/src/seeds/index.ts
@@ -9,9 +9,11 @@ import { name, internet, datatype } from 'faker'
 import { users } from './users/index'
 import { creations } from './creation/index'
 import { transactionLinks } from './transactionLink/index'
+import { contributionLinks } from './contributionLink/index'
 import { userFactory } from './factory/user'
 import { creationFactory } from './factory/creation'
 import { transactionLinkFactory } from './factory/transactionLink'
+import { contributionLinkFactory } from './factory/contributionLink'
 import { entities } from '@entity/index'
 import CONFIG from '@/config'
 
@@ -77,6 +79,11 @@ const run = async () => {
     await transactionLinkFactory(seedClient, transactionLinks[i])
   }
 
+  // create Contribution Links
+  for (let i = 0; i < contributionLinks.length; i++) {
+    await contributionLinkFactory(seedClient, contributionLinks[i])
+  }
+
   await con.close()
 }
 
diff --git a/backend/src/typeorm/repository/UserSettingRepository.ts b/backend/src/typeorm/repository/UserSettingRepository.ts
deleted file mode 100644
index f911cfd1a..000000000
--- a/backend/src/typeorm/repository/UserSettingRepository.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { EntityRepository, Repository } from '@dbTools/typeorm'
-import { UserSetting } from '@entity/UserSetting'
-import { isStringBoolean } from '@/util/validate'
-
-@EntityRepository(UserSetting)
-export class UserSettingRepository extends Repository<UserSetting> {
-  async setOrUpdate(userId: number, value: string): Promise<UserSetting> {
-    let entity = await this.findOne({ userId: userId })
-
-    if (!entity) {
-      entity = new UserSetting()
-      entity.userId = userId
-    }
-    entity.value = value
-    return this.save(entity)
-  }
-
-  async readBoolean(userId: number): Promise<boolean> {
-    const entity = await this.findOne({ userId: userId })
-    if (!entity || !isStringBoolean(entity.value)) {
-      return true
-    }
-    return entity.value.toLowerCase() === 'true'
-  }
-}
diff --git a/backend/src/util/communityUser.ts b/backend/src/util/communityUser.ts
index 0d0d12f6c..1a84c2cdf 100644
--- a/backend/src/util/communityUser.ts
+++ b/backend/src/util/communityUser.ts
@@ -20,7 +20,6 @@ const communityDbUser: dbUser = {
   isAdmin: null,
   publisherId: 0,
   passphrase: '',
-  settings: [],
   hasId: function (): boolean {
     throw new Error('Function not implemented.')
   },
diff --git a/database/README.md b/database/README.md
index d6cf84518..e951f4530 100644
--- a/database/README.md
+++ b/database/README.md
@@ -1,32 +1,39 @@
 # database
 
 ## Project setup
-```
+
+```bash
 yarn install
 ```
 
 ## Upgrade migrations production
-```
+
+```bash
 yarn up
 ```
 
 ## Upgrade migrations development
-```
+
+```bash
 yarn dev_up
 ```
 
 ## Downgrade migrations production
-```
+
+```bash
 yarn down
 ```
 
 ## Downgrade migrations development
-```
+
+```bash
 yarn dev_down
 ```
 
 ## Reset database
-```
+
+```bash
 yarn dev_reset
 ```
+
 Runs all down migrations and after this all up migrations.
diff --git a/database/entity/0002-add_settings/User.ts b/database/entity/0002-add_settings/User.ts
index a756cbbd5..4f333fd50 100644
--- a/database/entity/0002-add_settings/User.ts
+++ b/database/entity/0002-add_settings/User.ts
@@ -1,5 +1,5 @@
 import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 // Moriz: I do not like the idea of having two user tables
 @Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
diff --git a/database/entity/0002-add_settings/UserSetting.ts b/database/entity/0002-add_settings/UserSetting.ts
index 006d63e3e..9da036954 100644
--- a/database/entity/0002-add_settings/UserSetting.ts
+++ b/database/entity/0002-add_settings/UserSetting.ts
@@ -1,5 +1,5 @@
 import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
-import { User } from '../User'
+import { User } from '../0034-drop_server_user_table/User'
 
 @Entity()
 export class UserSetting extends BaseEntity {
diff --git a/database/entity/0017-combine_user_tables/User.ts b/database/entity/0017-combine_user_tables/User.ts
index a9bf29d24..7281c4773 100644
--- a/database/entity/0017-combine_user_tables/User.ts
+++ b/database/entity/0017-combine_user_tables/User.ts
@@ -1,5 +1,5 @@
 import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 @Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
 export class User extends BaseEntity {
diff --git a/database/entity/0018-combine_login_user_backups_and_user_table/User.ts b/database/entity/0018-combine_login_user_backups_and_user_table/User.ts
index 2ae351e47..347f51a8d 100644
--- a/database/entity/0018-combine_login_user_backups_and_user_table/User.ts
+++ b/database/entity/0018-combine_login_user_backups_and_user_table/User.ts
@@ -1,5 +1,5 @@
 import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 @Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
 export class User extends BaseEntity {
diff --git a/database/entity/0019-replace_login_user_id_with_state_user_id/User.ts b/database/entity/0019-replace_login_user_id_with_state_user_id/User.ts
index b469a55a7..8c00ec5c3 100644
--- a/database/entity/0019-replace_login_user_id_with_state_user_id/User.ts
+++ b/database/entity/0019-replace_login_user_id_with_state_user_id/User.ts
@@ -1,5 +1,5 @@
 import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 @Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
 export class User extends BaseEntity {
diff --git a/database/entity/0020-rename_and_clean_state_users/User.ts b/database/entity/0020-rename_and_clean_state_users/User.ts
index 3d3b4d7b1..5501bccba 100644
--- a/database/entity/0020-rename_and_clean_state_users/User.ts
+++ b/database/entity/0020-rename_and_clean_state_users/User.ts
@@ -1,5 +1,5 @@
 import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 @Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
 export class User extends BaseEntity {
diff --git a/database/entity/0023-users_disabled_soft_delete/User.ts b/database/entity/0023-users_disabled_soft_delete/User.ts
index 95fe1b3f7..950e74aeb 100644
--- a/database/entity/0023-users_disabled_soft_delete/User.ts
+++ b/database/entity/0023-users_disabled_soft_delete/User.ts
@@ -6,7 +6,7 @@ import {
   OneToMany,
   DeleteDateColumn,
 } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 @Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
 export class User extends BaseEntity {
diff --git a/database/entity/0033-add_referrer_id/User.ts b/database/entity/0033-add_referrer_id/User.ts
index 48c804b63..353c6a830 100644
--- a/database/entity/0033-add_referrer_id/User.ts
+++ b/database/entity/0033-add_referrer_id/User.ts
@@ -6,7 +6,7 @@ import {
   OneToMany,
   DeleteDateColumn,
 } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 @Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
 export class User extends BaseEntity {
diff --git a/database/entity/0034-drop_server_user_table/User.ts b/database/entity/0034-drop_server_user_table/User.ts
index 1f56d13d2..82fd72009 100644
--- a/database/entity/0034-drop_server_user_table/User.ts
+++ b/database/entity/0034-drop_server_user_table/User.ts
@@ -6,7 +6,7 @@ import {
   OneToMany,
   DeleteDateColumn,
 } from 'typeorm'
-import { UserSetting } from '../UserSetting'
+import { UserSetting } from '../0002-add_settings/UserSetting'
 
 @Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
 export class User extends BaseEntity {
diff --git a/database/entity/0037-drop_user_setting_table/User.ts b/database/entity/0037-drop_user_setting_table/User.ts
new file mode 100644
index 000000000..528cef32b
--- /dev/null
+++ b/database/entity/0037-drop_user_setting_table/User.ts
@@ -0,0 +1,70 @@
+import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, DeleteDateColumn } from 'typeorm'
+
+@Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
+export class User extends BaseEntity {
+  @PrimaryGeneratedColumn('increment', { unsigned: true })
+  id: number
+
+  @Column({ name: 'public_key', type: 'binary', length: 32, default: null, nullable: true })
+  pubKey: Buffer
+
+  @Column({ name: 'privkey', type: 'binary', length: 80, default: null, nullable: true })
+  privKey: Buffer
+
+  @Column({ length: 255, unique: true, nullable: false, collation: 'utf8mb4_unicode_ci' })
+  email: string
+
+  @Column({
+    name: 'first_name',
+    length: 255,
+    nullable: true,
+    default: null,
+    collation: 'utf8mb4_unicode_ci',
+  })
+  firstName: string
+
+  @Column({
+    name: 'last_name',
+    length: 255,
+    nullable: true,
+    default: null,
+    collation: 'utf8mb4_unicode_ci',
+  })
+  lastName: string
+
+  @DeleteDateColumn()
+  deletedAt: Date | null
+
+  @Column({ type: 'bigint', default: 0, unsigned: true })
+  password: BigInt
+
+  @Column({ name: 'email_hash', type: 'binary', length: 32, default: null, nullable: true })
+  emailHash: Buffer
+
+  @Column({ name: 'created', default: () => 'CURRENT_TIMESTAMP', nullable: false })
+  createdAt: Date
+
+  @Column({ name: 'email_checked', type: 'bool', nullable: false, default: false })
+  emailChecked: boolean
+
+  @Column({ length: 4, default: 'de', collation: 'utf8mb4_unicode_ci', nullable: false })
+  language: string
+
+  @Column({ name: 'is_admin', type: 'datetime', nullable: true, default: null })
+  isAdmin: Date | null
+
+  @Column({ name: 'referrer_id', type: 'int', unsigned: true, nullable: true, default: null })
+  referrerId?: number | null
+
+  @Column({ name: 'publisher_id', default: 0 })
+  publisherId: number
+
+  @Column({
+    type: 'text',
+    name: 'passphrase',
+    collation: 'utf8mb4_unicode_ci',
+    nullable: true,
+    default: null,
+  })
+  passphrase: string
+}
diff --git a/database/entity/0038-add_contribution_links_table/ContributionLink.ts b/database/entity/0038-add_contribution_links_table/ContributionLink.ts
new file mode 100644
index 000000000..496f57d71
--- /dev/null
+++ b/database/entity/0038-add_contribution_links_table/ContributionLink.ts
@@ -0,0 +1,88 @@
+import Decimal from 'decimal.js-light'
+import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, DeleteDateColumn } from 'typeorm'
+import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer'
+
+@Entity('contribution_links')
+export class ContributionLink extends BaseEntity {
+  @PrimaryGeneratedColumn('increment', { unsigned: true })
+  id: number
+
+  @Column({ length: 100, nullable: false, collation: 'utf8mb4_unicode_ci' })
+  name: string
+
+  @Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' })
+  memo: string
+
+  @Column({ name: 'valid_from', type: 'datetime', nullable: false })
+  validFrom: Date
+
+  @Column({ name: 'valid_to', type: 'datetime', nullable: true, default: null })
+  validTo: Date | null
+
+  @Column({
+    type: 'decimal',
+    precision: 40,
+    scale: 20,
+    nullable: false,
+    transformer: DecimalTransformer,
+  })
+  amount: Decimal
+
+  @Column({ length: 12, nullable: false, collation: 'utf8mb4_unicode_ci' })
+  cycle: string
+
+  @Column({ name: 'max_per_cycle', unsigned: true, nullable: false, default: 1 })
+  maxPerCycle: number
+
+  @Column({
+    name: 'max_amount_per_month',
+    type: 'decimal',
+    precision: 40,
+    scale: 20,
+    nullable: true,
+    default: null,
+    transformer: DecimalTransformer,
+  })
+  maxAmountPerMonth: Decimal | null
+
+  @Column({
+    name: 'total_max_count_of_contribution',
+    type: 'int',
+    unsigned: true,
+    nullable: true,
+    default: null,
+  })
+  totalMaxCountOfContribution: number | null
+
+  @Column({
+    name: 'max_account_balance',
+    type: 'decimal',
+    precision: 40,
+    scale: 20,
+    nullable: true,
+    default: null,
+    transformer: DecimalTransformer,
+  })
+  maxAccountBalance: Decimal | null
+
+  @Column({
+    name: 'min_gap_hours',
+    type: 'int',
+    unsigned: true,
+    nullable: true,
+    default: null,
+  })
+  minGapHours: number | null
+
+  @Column({ name: 'created_at', type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
+  createdAt: Date
+
+  @DeleteDateColumn({ name: 'deleted_at' })
+  deletedAt: Date | null
+
+  @Column({ length: 24, nullable: false, collation: 'utf8mb4_unicode_ci' })
+  code: string
+
+  @Column({ name: 'link_enabled', type: 'boolean', default: true })
+  linkEnabled: boolean
+}
diff --git a/database/entity/ContributionLink.ts b/database/entity/ContributionLink.ts
new file mode 100644
index 000000000..c7e4e2b7e
--- /dev/null
+++ b/database/entity/ContributionLink.ts
@@ -0,0 +1 @@
+export { ContributionLink } from './0038-add_contribution_links_table/ContributionLink'
diff --git a/database/entity/User.ts b/database/entity/User.ts
index 4cd68174c..2d434799e 100644
--- a/database/entity/User.ts
+++ b/database/entity/User.ts
@@ -1 +1 @@
-export { User } from './0034-drop_server_user_table/User'
+export { User } from './0037-drop_user_setting_table/User'
diff --git a/database/entity/UserSetting.ts b/database/entity/UserSetting.ts
deleted file mode 100644
index 38da380f9..000000000
--- a/database/entity/UserSetting.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { UserSetting } from './0002-add_settings/UserSetting'
diff --git a/database/entity/index.ts b/database/entity/index.ts
index 542333755..991e482e9 100644
--- a/database/entity/index.ts
+++ b/database/entity/index.ts
@@ -1,19 +1,19 @@
+import { ContributionLink } from './ContributionLink'
 import { LoginElopageBuys } from './LoginElopageBuys'
 import { LoginEmailOptIn } from './LoginEmailOptIn'
 import { Migration } from './Migration'
 import { Transaction } from './Transaction'
 import { TransactionLink } from './TransactionLink'
 import { User } from './User'
-import { UserSetting } from './UserSetting'
 import { AdminPendingCreation } from './AdminPendingCreation'
 
 export const entities = [
   AdminPendingCreation,
+  ContributionLink,
   LoginElopageBuys,
   LoginEmailOptIn,
   Migration,
   Transaction,
   TransactionLink,
   User,
-  UserSetting,
 ]
diff --git a/database/migrations/0037-drop_user_setting_table.ts b/database/migrations/0037-drop_user_setting_table.ts
new file mode 100644
index 000000000..50a78e104
--- /dev/null
+++ b/database/migrations/0037-drop_user_setting_table.ts
@@ -0,0 +1,19 @@
+/* MIGRATION DROP user_setting TABLE */
+
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
+  await queryFn('DROP TABLE `user_setting`;')
+}
+
+export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
+  await queryFn(`
+    CREATE TABLE IF NOT EXISTS \`user_setting\` (
+      \`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
+      \`userId\` int(11) NOT NULL,
+      \`key\` varchar(255) NOT NULL,
+      \`value\` varchar(255) NOT NULL,
+      PRIMARY KEY (\`id\`)
+    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
+}
diff --git a/database/migrations/0038-add_contribution_links_table.ts b/database/migrations/0038-add_contribution_links_table.ts
new file mode 100644
index 000000000..f983644cc
--- /dev/null
+++ b/database/migrations/0038-add_contribution_links_table.ts
@@ -0,0 +1,35 @@
+/* MIGRATION TO ADD CONTRIBUTION_LINKS
+ *
+ * This migration adds the table `contribution_links` in order to store all sorts of contribution_links data
+ */
+
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
+  await queryFn(`
+      CREATE TABLE IF NOT EXISTS \`contribution_links\` (
+        \`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
+        \`name\` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
+        \`memo\` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
+        \`valid_from\` datetime NOT NULL,
+        \`valid_to\` datetime NULL,
+        \`amount\` bigint(20) NOT NULL,
+        \`cycle\` varchar(12) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'ONCE',
+        \`max_per_cycle\` int(10) unsigned NOT NULL DEFAULT '1',
+        \`max_amount_per_month\` bigint(20) NULL DEFAULT NULL,
+        \`total_max_count_of_contribution\` int(10) unsigned NULL DEFAULT NULL,
+        \`max_account_balance\` bigint(20) NULL DEFAULT NULL,
+        \`min_gap_hours\` int(10) unsigned NULL DEFAULT NULL,
+        \`created_at\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+        \`deleted_at\` datetime NULL DEFAULT NULL,
+        \`code\` varchar(24) COLLATE utf8mb4_unicode_ci NOT NULL,
+        \`link_enabled\` tinyint(4) NOT NULL DEFAULT '1',
+        PRIMARY KEY (\`id\`)
+      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
+}
+
+export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
+  // write downgrade logic as parameter of queryFn
+  await queryFn(`DROP TABLE IF EXISTS \`contribution_links\`;`)
+}
diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist
index a1751a859..d9e159382 100644
--- a/deployment/bare_metal/.env.dist
+++ b/deployment/bare_metal/.env.dist
@@ -22,10 +22,11 @@ COMMUNITY_NAME="Gradido Development Stage1"
 COMMUNITY_URL=https://stage1.gradido.net/
 COMMUNITY_REGISTER_URL=https://stage1.gradido.net/register
 COMMUNITY_REDEEM_URL=https://stage1.gradido.net/redeem/{code}
+COMMUNITY_REDEEM_CONTRIBUTION_URL=https://stage1.gradido.net/redeem/CL-{code}
 COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community"
 
 # backend
-BACKEND_CONFIG_VERSION=v6.2022-04-21
+BACKEND_CONFIG_VERSION=v7.2022-06-15
 
 JWT_EXPIRES_IN=30m
 GDT_API_URL=https://gdt.gradido.net
diff --git a/frontend/src/components/Auth/AuthNavbar.vue b/frontend/src/components/Auth/AuthNavbar.vue
index 7b3eed0e3..8063dd330 100644
--- a/frontend/src/components/Auth/AuthNavbar.vue
+++ b/frontend/src/components/Auth/AuthNavbar.vue
@@ -20,7 +20,7 @@
 
       <b-collapse id="nav-collapse" is-nav class="mt-5 mt-lg-0">
         <b-navbar-nav class="ml-auto" right>
-          <b-nav-item href="https://gradido.net/de/" target="_blank">
+          <b-nav-item :href="`https://gradido.net/${$i18n.locale}`" target="_blank">
             {{ $t('auth.navbar.aboutGradido') }}
           </b-nav-item>
           <b-nav-item to="/register" class="authNavbar ml-lg-5">{{ $t('signup') }}</b-nav-item>
