# Issue tickets after payment (/docs/guides/payments)



Use your payment provider for checkout. Use Eventlayer to issue the ticket.

<DocsFlow label="Paid registration" steps="[&#x22;Payment confirmed&#x22;, &#x22;Your backend&#x22;, &#x22;Ticket issued&#x22;]" />

## 1. Confirm the payment [#1-confirm-the-payment]

Verify your payment provider’s webhook and match it to a paid order in your
database. Use the order’s event and attendee IDs; a browser redirect is not
proof of payment.

Create the attendee with the [registration flow](/docs/guides/website-registration)
if you have not already saved one.

## 2. Issue the ticket [#2-issue-the-ticket]

Once your backend confirms the order is paid, create its ticket.

```ts title="Paid order · server"
import { Eventlayer } from "eventlayer";

const eventlayer = new Eventlayer();
const { data: ticket, error } = await eventlayer.tickets.create({
  eventId: order.eventId,
  attendeeId: order.attendeeId,
  ticketTypeId: order.ticketTypeId,
});
if (error) throw error;
```

Save ticket.id on the order and show your confirmation page. If a payment
notification arrives again, reuse the saved ticket. See
[retries and recovery](/docs/retries) for partial failures.

## Refunds and access removal [#refunds-and-access-removal]

A refund through your payment provider does not remove the Eventlayer ticket.
When your refund policy requires it, remove access using the saved ticket ID.

```ts title="Remove access · server"
const { error } = await eventlayer.tickets.delete({
  ticketId: order.ticketId,
});
if (error) throw error;
```

This removes access. A registered Wallet device keeps a cancelled ticket
record; otherwise the ticket is deleted. Keep the order in your own database.

## Next steps [#next-steps]

[Send the ticket email](/docs/guides/email) or [add a Wallet pass](/docs/guides/apple-wallet).
